libpurple/plugins/tcl/tcl_cmds.c

changeset 37581
1fb661b5f206
parent 37580
498763742ea4
child 37582
ca3533cdddc7
equal deleted inserted replaced
37580:498763742ea4 37581:1fb661b5f206
1 /**
2 * @file tcl_cmds.c Commands for the Purple Tcl plugin bindings
3 *
4 * purple
5 *
6 * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 */
22
23 #include <tcl.h>
24
25 #include "internal.h"
26 #include "conversation.h"
27 #include "connection.h"
28 #include "eventloop.h"
29 #include "account.h"
30 #include "server.h"
31 #include "notify.h"
32 #include "buddylist.h"
33 #include "savedstatuses.h"
34 #include "debug.h"
35 #include "prefs.h"
36 #include "presence.h"
37 #include "core.h"
38
39 #include "tcl_purple.h"
40
41 static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp);
42 static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp);
43 static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp);
44
45 static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp)
46 {
47 PurpleAccount *account;
48 GList *cur;
49
50 account = purple_tcl_ref_get(interp, obj, PurpleTclRefAccount);
51
52 if (account == NULL)
53 return NULL;
54
55 for (cur = purple_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
56 if (account == cur->data)
57 return account;
58 }
59 if (interp != NULL)
60 Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid account", -1));
61 return NULL;
62 }
63
64 static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp)
65 {
66 PurpleConversation *convo;
67 GList *cur;
68
69 convo = purple_tcl_ref_get(interp, obj, PurpleTclRefConversation);
70
71 if (convo == NULL)
72 return NULL;
73
74 for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) {
75 if (convo == cur->data)
76 return convo;
77 }
78 if (interp != NULL)
79 Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid conversation", -1));
80 return NULL;
81 }
82
83 static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp)
84 {
85 PurpleConnection *gc;
86 GList *cur;
87
88 gc = purple_tcl_ref_get(interp, obj, PurpleTclRefConnection);
89
90 if (gc == NULL)
91 return NULL;
92
93 for (cur = purple_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
94 if (gc == cur->data)
95 return gc;
96 }
97 return NULL;
98 }
99
100 int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
101 {
102 Tcl_Obj *result, *list, *elem;
103 const char *cmds[] = { "alias", "connect", "connection", "disconnect",
104 "enabled", "find", "handle", "isconnected",
105 "list", "presence", "protocol", "status",
106 "status_type", "status_types", "username",
107 NULL };
108 enum { CMD_ACCOUNT_ALIAS,
109 CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION,
110 CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_ENABLED, CMD_ACCOUNT_FIND,
111 CMD_ACCOUNT_HANDLE, CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST,
112 CMD_ACCOUNT_PRESENCE, CMD_ACCOUNT_PROTOCOL, CMD_ACCOUNT_STATUS,
113 CMD_ACCOUNT_STATUS_TYPE, CMD_ACCOUNT_STATUS_TYPES,
114 CMD_ACCOUNT_USERNAME } cmd;
115 const char *listopts[] = { "-all", "-online", NULL };
116 enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
117 const char *alias;
118 GList *cur;
119 PurpleAccount *account;
120 PurpleStatus *status;
121 PurpleStatusType *status_type;
122 GValue *value;
123 char *attr_id;
124 int error;
125 int b, i;
126
127 if (objc < 2) {
128 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
129 return TCL_ERROR;
130 }
131
132 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
133 return error;
134
135 switch (cmd) {
136 case CMD_ACCOUNT_ALIAS:
137 if (objc != 3) {
138 Tcl_WrongNumArgs(interp, 2, objv, "account");
139 return TCL_ERROR;
140 }
141 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
142 return TCL_ERROR;
143 alias = purple_account_get_private_alias(account);
144 Tcl_SetObjResult(interp, Tcl_NewStringObj(alias ? (char *)alias : "", -1));
145 break;
146 case CMD_ACCOUNT_CONNECT:
147 if (objc != 3) {
148 Tcl_WrongNumArgs(interp, 2, objv, "account");
149 return TCL_ERROR;
150 }
151 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
152 return TCL_ERROR;
153 if (!purple_account_is_connected(account))
154 purple_account_connect(account);
155 Tcl_SetObjResult(interp,
156 purple_tcl_ref_new(PurpleTclRefConnection,
157 purple_account_get_connection(account)));
158 break;
159 case CMD_ACCOUNT_CONNECTION:
160 if (objc != 3) {
161 Tcl_WrongNumArgs(interp, 2, objv, "account");
162 return TCL_ERROR;
163 }
164
165 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
166 return TCL_ERROR;
167 Tcl_SetObjResult(interp,
168 purple_tcl_ref_new(PurpleTclRefConnection,
169 purple_account_get_connection(account)));
170 break;
171 case CMD_ACCOUNT_DISCONNECT:
172 if (objc != 3) {
173 Tcl_WrongNumArgs(interp, 2, objv, "account");
174 return TCL_ERROR;
175 }
176 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
177 return TCL_ERROR;
178 purple_account_disconnect(account);
179 break;
180 case CMD_ACCOUNT_ENABLED:
181 if (objc != 3 && objc != 4) {
182 Tcl_WrongNumArgs(interp, 2, objv, "account ?enabled?");
183 return TCL_ERROR;
184 }
185 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
186 return TCL_ERROR;
187 if (objc == 3) {
188 Tcl_SetObjResult(interp,
189 Tcl_NewBooleanObj(
190 purple_account_get_enabled(account,
191 purple_core_get_ui())));
192 } else {
193 if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &b)) != TCL_OK)
194 return TCL_ERROR;
195 purple_account_set_enabled(account, purple_core_get_ui(), b);
196 }
197 break;
198 case CMD_ACCOUNT_FIND:
199 if (objc != 4) {
200 Tcl_WrongNumArgs(interp, 2, objv, "username protocol");
201 return TCL_ERROR;
202 }
203 account = purple_accounts_find(Tcl_GetString(objv[2]),
204 Tcl_GetString(objv[3]));
205 Tcl_SetObjResult(interp,
206 purple_tcl_ref_new(PurpleTclRefAccount, account));
207 break;
208 case CMD_ACCOUNT_HANDLE:
209 if (objc != 2) {
210 Tcl_WrongNumArgs(interp, 2, objv, "");
211 return TCL_ERROR;
212 }
213 Tcl_SetObjResult(interp,
214 purple_tcl_ref_new(PurpleTclRefHandle,
215 purple_accounts_get_handle()));
216 break;
217 case CMD_ACCOUNT_ISCONNECTED:
218 if (objc != 3) {
219 Tcl_WrongNumArgs(interp, 2, objv, "account");
220 return TCL_ERROR;
221 }
222 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
223 return TCL_ERROR;
224 Tcl_SetObjResult(interp,
225 Tcl_NewBooleanObj(
226 purple_account_is_connected(account)));
227 break;
228 case CMD_ACCOUNT_LIST:
229 listopt = CMD_ACCOUNTLIST_ALL;
230 if (objc > 3) {
231 Tcl_WrongNumArgs(interp, 2, objv, "?option?");
232 return TCL_ERROR;
233 }
234 if (objc == 3) {
235 if ((error = Tcl_GetIndexFromObj(interp, objv[2], listopts, "option", 0, (int *)&listopt)) != TCL_OK)
236 return error;
237 }
238 list = Tcl_NewListObj(0, NULL);
239 for (cur = purple_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
240 account = cur->data;
241 if (listopt == CMD_ACCOUNTLIST_ONLINE && !purple_account_is_connected(account))
242 continue;
243 elem = purple_tcl_ref_new(PurpleTclRefAccount, account);
244 Tcl_ListObjAppendElement(interp, list, elem);
245 }
246 Tcl_SetObjResult(interp, list);
247 break;
248 case CMD_ACCOUNT_PRESENCE:
249 if (objc != 3) {
250 Tcl_WrongNumArgs(interp, 2, objv, "account");
251 return TCL_ERROR;
252 }
253 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
254 return TCL_ERROR;
255 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefPresence,
256 purple_account_get_presence(account)));
257 break;
258 case CMD_ACCOUNT_PROTOCOL:
259 if (objc != 3) {
260 Tcl_WrongNumArgs(interp, 2, objv, "account");
261 return TCL_ERROR;
262 }
263 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
264 return TCL_ERROR;
265 Tcl_SetObjResult(interp, Tcl_NewStringObj((char *)purple_account_get_protocol_id(account), -1));
266 break;
267 case CMD_ACCOUNT_STATUS:
268 if (objc < 3) {
269 Tcl_WrongNumArgs(interp, 2, objv, "account ?status_id name value ...?");
270 return TCL_ERROR;
271 }
272 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
273 return TCL_ERROR;
274 if (objc == 3) {
275 Tcl_SetObjResult(interp,
276 purple_tcl_ref_new(PurpleTclRefStatus,
277 purple_account_get_active_status(account)));
278 } else {
279 GList *l = NULL;
280 if (objc % 2) {
281 Tcl_SetObjResult(interp, Tcl_NewStringObj("name without value setting status", -1));
282 return TCL_ERROR;
283 }
284 status = purple_account_get_status(account, Tcl_GetString(objv[3]));
285 if (status == NULL) {
286 Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid status for account", -1));
287 return TCL_ERROR;
288 }
289 for (i = 4; i < objc; i += 2) {
290 attr_id = Tcl_GetString(objv[i]);
291 value = purple_status_get_attr_value(status, attr_id);
292 if (value == NULL) {
293 Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid attribute for account", -1));
294 return TCL_ERROR;
295 }
296 switch (G_VALUE_TYPE(value)) {
297 case G_TYPE_BOOLEAN:
298 error = Tcl_GetBooleanFromObj(interp, objv[i + 1], &b);
299 if (error != TCL_OK)
300 return error;
301 l = g_list_append(l, attr_id);
302 l = g_list_append(l, GINT_TO_POINTER(b));
303 break;
304 case G_TYPE_INT:
305 error = Tcl_GetIntFromObj(interp, objv[i + 1], &b);
306 if (error != TCL_OK)
307 return error;
308 l = g_list_append(l, attr_id);
309 l = g_list_append(l, GINT_TO_POINTER(b));
310 break;
311 case G_TYPE_STRING:
312 l = g_list_append(l, attr_id);
313 l = g_list_append(l, Tcl_GetString(objv[i + 1]));
314 break;
315 default:
316 Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown GValue type", -1));
317 return TCL_ERROR;
318 }
319 }
320 purple_account_set_status_list(account, Tcl_GetString(objv[3]), TRUE, l);
321 g_list_free(l);
322 }
323 break;
324 case CMD_ACCOUNT_STATUS_TYPE:
325 if (objc != 4 && objc != 5) {
326 Tcl_WrongNumArgs(interp, 2, objv, "account ?statustype? ?-primitive primitive?");
327 return TCL_ERROR;
328 }
329 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
330 return TCL_ERROR;
331 if (objc == 4) {
332 status_type = purple_account_get_status_type(account,
333 Tcl_GetString(objv[3]));
334 } else {
335 PurpleStatusPrimitive primitive;
336 if (strcmp(Tcl_GetString(objv[3]), "-primitive")) {
337 result = Tcl_NewStringObj("bad option \"", -1);
338 Tcl_AppendObjToObj(result, objv[3]);
339 Tcl_AppendToObj(result, "\": should be -primitive", -1);
340 Tcl_SetObjResult(interp,result);
341 return TCL_ERROR;
342 }
343 primitive = purple_primitive_get_type_from_id(Tcl_GetString(objv[4]));
344 status_type = purple_account_get_status_type_with_primitive(account,
345 primitive);
346 }
347 if (status_type == NULL) {
348 Tcl_SetObjResult(interp, Tcl_NewStringObj("status type not found", -1));
349 return TCL_ERROR;
350 }
351 Tcl_SetObjResult(interp,
352 purple_tcl_ref_new(PurpleTclRefStatusType,
353 status_type));
354 break;
355 case CMD_ACCOUNT_STATUS_TYPES:
356 if (objc != 3) {
357 Tcl_WrongNumArgs(interp, 2, objv, "account");
358 return TCL_ERROR;
359 }
360 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
361 return TCL_ERROR;
362 list = Tcl_NewListObj(0, NULL);
363 for (cur = purple_account_get_status_types(account); cur != NULL;
364 cur = g_list_next(cur)) {
365 Tcl_ListObjAppendElement(interp, list,
366 purple_tcl_ref_new(PurpleTclRefStatusType,
367 cur->data));
368 }
369 Tcl_SetObjResult(interp, list);
370 break;
371 case CMD_ACCOUNT_USERNAME:
372 if (objc != 3) {
373 Tcl_WrongNumArgs(interp, 2, objv, "account");
374 return TCL_ERROR;
375 }
376 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
377 return TCL_ERROR;
378 Tcl_SetObjResult(interp,
379 Tcl_NewStringObj((char *)purple_account_get_username(account), -1));
380 break;
381 }
382
383 return TCL_OK;
384 }
385
386 static PurpleBlistNode *tcl_list_to_buddy(Tcl_Interp *interp, int count, Tcl_Obj **elems)
387 {
388 PurpleBlistNode *node = NULL;
389 PurpleAccount *account;
390 char *name;
391 char *type;
392
393 if (count < 3) {
394 Tcl_SetObjResult(interp,
395 Tcl_NewStringObj("list too short", -1));
396 return NULL;
397 }
398
399 type = Tcl_GetString(elems[0]);
400 name = Tcl_GetString(elems[1]);
401 if ((account = tcl_validate_account(elems[2], interp)) == NULL)
402 return NULL;
403
404 if (!strcmp(type, "buddy")) {
405 node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, name));
406 } else if (!strcmp(type, "group")) {
407 node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, name));
408 }
409
410 return node;
411 }
412
413 int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
414 {
415 Tcl_Obj *list, *tclgroup, *tclgrouplist, *tclcontact, *tclcontactlist, *tclbud, **elems, *result;
416 const char *cmds[] = { "alias", "handle", "info", "list", NULL };
417 enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd;
418 PurpleBlistNode *node, *gnode, *bnode;
419 PurpleAccount *account;
420 PurpleBuddy *bud;
421 PurpleChat *cnode;
422 int error, all = 0, count;
423
424 if (objc < 2) {
425 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
426 return TCL_ERROR;
427 }
428 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
429 return error;
430
431 switch (cmd) {
432 case CMD_BUDDY_ALIAS:
433 if (objc != 3) {
434 Tcl_WrongNumArgs(interp, 2, objv, "buddy");
435 return TCL_ERROR;
436 }
437 if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
438 return error;
439 if ((node = tcl_list_to_buddy(interp, count, elems)) == NULL)
440 return TCL_ERROR;
441 if (PURPLE_IS_CHAT(node))
442 Tcl_SetObjResult(interp,
443 Tcl_NewStringObj(purple_chat_get_name(PURPLE_CHAT(node)), -1));
444 else if (PURPLE_IS_BUDDY(node))
445 Tcl_SetObjResult(interp,
446 Tcl_NewStringObj((char *)purple_buddy_get_alias(PURPLE_BUDDY(node)), -1));
447 return TCL_OK;
448 break;
449 case CMD_BUDDY_HANDLE:
450 if (objc != 2) {
451 Tcl_WrongNumArgs(interp, 2, objv, "");
452 return TCL_ERROR;
453 }
454 Tcl_SetObjResult(interp,
455 purple_tcl_ref_new(PurpleTclRefHandle,
456 purple_blist_get_handle()));
457 break;
458 case CMD_BUDDY_INFO:
459 if (objc != 3 && objc != 4) {
460 Tcl_WrongNumArgs(interp, 2, objv, "( buddy | account username )");
461 return TCL_ERROR;
462 }
463 if (objc == 3) {
464 if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
465 return error;
466 if (count < 3) {
467 Tcl_SetObjResult(interp,
468 Tcl_NewStringObj("buddy too short", -1));
469 return TCL_ERROR;
470 }
471 if (strcmp("buddy", Tcl_GetString(elems[0]))) {
472 Tcl_SetObjResult(interp,
473 Tcl_NewStringObj("invalid buddy", -1));
474 return TCL_ERROR;
475 }
476 if ((account = tcl_validate_account(elems[2], interp)) == NULL)
477 return TCL_ERROR;
478 purple_serv_get_info(purple_account_get_connection(account), Tcl_GetString(elems[1]));
479 } else {
480 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
481 return TCL_ERROR;
482 purple_serv_get_info(purple_account_get_connection(account), Tcl_GetString(objv[3]));
483 }
484 break;
485 case CMD_BUDDY_LIST:
486 if (objc == 3) {
487 if (!strcmp("-all", Tcl_GetString(objv[2]))) {
488 all = 1;
489 } else {
490 result = Tcl_NewStringObj("",-1);
491 Tcl_AppendStringsToObj(result, "unknown option: ", Tcl_GetString(objv[2]), NULL);
492 Tcl_SetObjResult(interp,result);
493 return TCL_ERROR;
494 }
495 }
496 list = Tcl_NewListObj(0, NULL);
497 for (gnode = purple_blist_get_root(); gnode != NULL; gnode = purple_blist_node_get_sibling_next(gnode)) {
498 tclgroup = Tcl_NewListObj(0, NULL);
499 Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj("group", -1));
500 Tcl_ListObjAppendElement(interp, tclgroup,
501 Tcl_NewStringObj(purple_group_get_name(PURPLE_GROUP(gnode)), -1));
502 tclgrouplist = Tcl_NewListObj(0, NULL);
503 for (node = purple_blist_node_get_first_child(gnode); node != NULL; node = purple_blist_node_get_sibling_next(node)) {
504 PurpleAccount *account;
505
506 if (PURPLE_IS_CONTACT(node)) {
507 tclcontact = Tcl_NewListObj(0, NULL);
508 Tcl_IncrRefCount(tclcontact);
509 Tcl_ListObjAppendElement(interp, tclcontact, Tcl_NewStringObj("contact", -1));
510 tclcontactlist = Tcl_NewListObj(0, NULL);
511 Tcl_IncrRefCount(tclcontactlist);
512 count = 0;
513 for (bnode = purple_blist_node_get_first_child(node); bnode != NULL; bnode = purple_blist_node_get_sibling_next(bnode)) {
514 if (!PURPLE_IS_BUDDY(bnode))
515 continue;
516 bud = PURPLE_BUDDY(bnode);
517 account = purple_buddy_get_account(bud);
518 if (!all && !purple_account_is_connected(account))
519 continue;
520 count++;
521 tclbud = Tcl_NewListObj(0, NULL);
522 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("buddy", -1));
523 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(purple_buddy_get_name(bud), -1));
524 Tcl_ListObjAppendElement(interp, tclbud, purple_tcl_ref_new(PurpleTclRefAccount, account));
525 Tcl_ListObjAppendElement(interp, tclcontactlist, tclbud);
526 }
527 if (count) {
528 Tcl_ListObjAppendElement(interp, tclcontact, tclcontactlist);
529 Tcl_ListObjAppendElement(interp, tclgrouplist, tclcontact);
530 }
531 Tcl_DecrRefCount(tclcontact);
532 Tcl_DecrRefCount(tclcontactlist);
533 } else if (PURPLE_IS_CHAT(node)) {
534 cnode = PURPLE_CHAT(node);
535 account = purple_chat_get_account(cnode);
536 if (!all && !purple_account_is_connected(account))
537 continue;
538 tclbud = Tcl_NewListObj(0, NULL);
539 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("chat", -1));
540 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(purple_chat_get_name(cnode), -1));
541 Tcl_ListObjAppendElement(interp, tclbud, purple_tcl_ref_new(PurpleTclRefAccount, account));
542 Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud);
543 } else {
544 purple_debug(PURPLE_DEBUG_WARNING, "tcl", "Unexpected buddy type %s", G_OBJECT_TYPE_NAME(node));
545 continue;
546 }
547 }
548 Tcl_ListObjAppendElement(interp, tclgroup, tclgrouplist);
549 Tcl_ListObjAppendElement(interp, list, tclgroup);
550 }
551 Tcl_SetObjResult(interp, list);
552 break;
553 }
554
555 return TCL_OK;
556 }
557
558 int tcl_cmd_cmd(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
559 {
560 const char *cmds[] = { "do", "help", "list", "register", "unregister", NULL };
561 enum { CMD_CMD_DO, CMD_CMD_HELP, CMD_CMD_LIST, CMD_CMD_REGISTER, CMD_CMD_UNREGISTER } cmd;
562 struct tcl_cmd_handler *handler;
563 Tcl_Obj *list, *elem;
564 PurpleConversation *convo;
565 PurpleCmdId id;
566 PurpleCmdStatus status;
567 int error;
568 GList *l, *cur;
569 gchar *escaped, *errstr = NULL;
570
571 if (objc < 2) {
572 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
573 return TCL_ERROR;
574 }
575
576 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
577 return error;
578
579 switch (cmd) {
580 case CMD_CMD_DO:
581 if (objc != 4) {
582 Tcl_WrongNumArgs(interp, 2, objv, "conversation command");
583 return TCL_ERROR;
584 }
585 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
586 return TCL_ERROR;
587 escaped = g_markup_escape_text(Tcl_GetString(objv[3]), -1);
588 status = purple_cmd_do_command(convo, Tcl_GetString(objv[3]),
589 escaped, &errstr);
590 g_free(escaped);
591 Tcl_SetObjResult(interp,
592 Tcl_NewStringObj(errstr ? (char *)errstr : "", -1));
593 g_free(errstr);
594 if (status != PURPLE_CMD_STATUS_OK) {
595 return TCL_ERROR;
596 }
597 break;
598 case CMD_CMD_HELP:
599 if (objc != 4) {
600 Tcl_WrongNumArgs(interp, 2, objv, "conversation name");
601 return TCL_ERROR;
602 }
603 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
604 return TCL_ERROR;
605 l = cur = purple_cmd_help(convo, Tcl_GetString(objv[3]));
606 list = Tcl_NewListObj(0, NULL);
607 while (cur != NULL) {
608 elem = Tcl_NewStringObj((char *)cur->data, -1);
609 Tcl_ListObjAppendElement(interp, list, elem);
610 cur = g_list_next(cur);
611 }
612 g_list_free(l);
613 Tcl_SetObjResult(interp, list);
614 break;
615 case CMD_CMD_LIST:
616 if (objc != 3) {
617 Tcl_WrongNumArgs(interp, 2, objv, "conversation");
618 return TCL_ERROR;
619 }
620 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
621 return TCL_ERROR;
622 l = cur = purple_cmd_list(convo);
623 list = Tcl_NewListObj(0, NULL);
624 while (cur != NULL) {
625 elem = Tcl_NewStringObj((char *)cur->data, -1);
626 Tcl_ListObjAppendElement(interp, list, elem);
627 cur = g_list_next(cur);
628 }
629 g_list_free(l);
630 Tcl_SetObjResult(interp, list);
631 break;
632 case CMD_CMD_REGISTER:
633 if (objc != 9) {
634 Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags protocol_id proc helpstr");
635 return TCL_ERROR;
636 }
637 handler = g_new0(struct tcl_cmd_handler, 1);
638 handler->cmd = objv[2];
639 handler->args = Tcl_GetString(objv[3]);
640 handler->nargs = strlen(handler->args);
641 if ((error = Tcl_GetIntFromObj(interp, objv[4],
642 &handler->priority)) != TCL_OK) {
643 g_free(handler);
644 return error;
645 }
646 if ((error = Tcl_GetIntFromObj(interp, objv[5],
647 &handler->flags)) != TCL_OK) {
648 g_free(handler);
649 return error;
650 }
651 handler->protocol_id = Tcl_GetString(objv[6]);
652 handler->proc = objv[7];
653 handler->helpstr = Tcl_GetString(objv[8]);
654 handler->interp = interp;
655 if ((id = tcl_cmd_register(handler)) == 0) {
656 tcl_cmd_handler_free(handler);
657 Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
658 } else {
659 handler->id = id;
660 Tcl_SetObjResult(interp, Tcl_NewIntObj(id));
661 }
662 break;
663 case CMD_CMD_UNREGISTER:
664 if (objc != 3) {
665 Tcl_WrongNumArgs(interp, 2, objv, "id");
666 return TCL_ERROR;
667 }
668 if ((error = Tcl_GetIntFromObj(interp, objv[2],
669 (int *)&id)) != TCL_OK)
670 return error;
671 tcl_cmd_unregister(id, interp);
672 break;
673 }
674
675 return TCL_OK;
676 }
677
678 int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
679 {
680 Tcl_Obj *list, *elem;
681 const char *cmds[] = { "account", "displayname", "handle", "list", "state", NULL };
682 enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE,
683 CMD_CONN_LIST, CMD_CONN_STATE } cmd;
684 int error;
685 GList *cur;
686 PurpleConnection *gc;
687
688 if (objc < 2) {
689 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
690 return TCL_ERROR;
691 }
692
693 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
694 return error;
695
696 switch (cmd) {
697 case CMD_CONN_ACCOUNT:
698 if (objc != 3) {
699 Tcl_WrongNumArgs(interp, 2, objv, "gc");
700 return TCL_ERROR;
701 }
702 if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
703 return TCL_ERROR;
704 Tcl_SetObjResult(interp,
705 purple_tcl_ref_new(PurpleTclRefAccount,
706 purple_connection_get_account(gc)));
707 break;
708 case CMD_CONN_DISPLAYNAME:
709 if (objc != 3) {
710 Tcl_WrongNumArgs(interp, 2, objv, "gc");
711 return TCL_ERROR;
712 }
713 if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
714 return TCL_ERROR;
715 Tcl_SetObjResult(interp,
716 Tcl_NewStringObj(purple_connection_get_display_name(gc), -1));
717 break;
718 case CMD_CONN_HANDLE:
719 if (objc != 2) {
720 Tcl_WrongNumArgs(interp, 2, objv, "");
721 return TCL_ERROR;
722 }
723 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefHandle,
724 purple_connections_get_handle()));
725 break;
726 case CMD_CONN_LIST:
727 if (objc != 2) {
728 Tcl_WrongNumArgs(interp, 2, objv, "");
729 return TCL_ERROR;
730 }
731 list = Tcl_NewListObj(0, NULL);
732 for (cur = purple_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
733 elem = purple_tcl_ref_new(PurpleTclRefConnection, cur->data);
734 Tcl_ListObjAppendElement(interp, list, elem);
735 }
736 Tcl_SetObjResult(interp, list);
737 break;
738 case CMD_CONN_STATE:
739 if (objc != 3) {
740 Tcl_WrongNumArgs(interp, 2, objv, "gc");
741 return TCL_ERROR;
742 }
743 if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
744 return TCL_ERROR;
745 switch (purple_connection_get_state(gc)) {
746 case PURPLE_CONNECTION_DISCONNECTED:
747 Tcl_SetObjResult(interp, Tcl_NewStringObj("disconnected", -1));
748 break;
749 case PURPLE_CONNECTION_CONNECTED:
750 Tcl_SetObjResult(interp, Tcl_NewStringObj("connected", -1));
751 break;
752 case PURPLE_CONNECTION_CONNECTING:
753 Tcl_SetObjResult(interp, Tcl_NewStringObj("connecting", -1));
754 break;
755 }
756 break;
757 }
758
759 return TCL_OK;
760 }
761
762 int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
763 {
764 Tcl_Obj *list, *elem;
765 const char *cmds[] = { "find", "handle", "list", "new", "write", "name", "title", "send", NULL };
766 enum { CMD_CONV_FIND, CMD_CONV_HANDLE, CMD_CONV_LIST, CMD_CONV_NEW, CMD_CONV_WRITE , CMD_CONV_NAME, CMD_CONV_TITLE, CMD_CONV_SEND } cmd;
767 const char *styles[] = { "send", "recv", "system", NULL };
768 enum { CMD_CONV_WRITE_SEND, CMD_CONV_WRITE_RECV, CMD_CONV_WRITE_SYSTEM } style;
769 const char *newopts[] = { "-chat", "-im" };
770 enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt;
771 PurpleConversation *convo;
772 PurpleAccount *account;
773 PurpleMessage *pmsg;
774 gboolean is_chat = FALSE;
775 GList *cur;
776 char *opt, *from, *what;
777 int error, argsused;
778
779 if (objc < 2) {
780 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
781 return TCL_ERROR;
782 }
783
784 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
785 return error;
786
787 switch (cmd) {
788 case CMD_CONV_FIND:
789 if (objc != 4) {
790 Tcl_WrongNumArgs(interp, 2, objv, "account name");
791 return TCL_ERROR;
792 }
793 account = NULL;
794 if ((account = tcl_validate_account(objv[2], interp)) == NULL)
795 return TCL_ERROR;
796 convo = purple_conversations_find_with_account(Tcl_GetString(objv[3]),
797 account);
798 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo));
799 break;
800 case CMD_CONV_HANDLE:
801 if (objc != 2) {
802 Tcl_WrongNumArgs(interp, 2, objv, "");
803 return TCL_ERROR;
804 }
805 Tcl_SetObjResult(interp,
806 purple_tcl_ref_new(PurpleTclRefHandle,
807 purple_conversations_get_handle()));
808 break;
809 case CMD_CONV_LIST:
810 list = Tcl_NewListObj(0, NULL);
811 for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) {
812 elem = purple_tcl_ref_new(PurpleTclRefConversation, cur->data);
813 Tcl_ListObjAppendElement(interp, list, elem);
814 }
815 Tcl_SetObjResult(interp, list);
816 break;
817 case CMD_CONV_NEW:
818 if (objc < 4) {
819 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
820 return TCL_ERROR;
821 }
822 argsused = 2;
823 is_chat = FALSE;
824 while (argsused < objc) {
825 opt = Tcl_GetString(objv[argsused]);
826 if (*opt == '-') {
827 if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], newopts,
828 "option", 0, (int *)&newopt)) != TCL_OK)
829 return error;
830 argsused++;
831 switch (newopt) {
832 case CMD_CONV_NEW_CHAT:
833 is_chat = TRUE;
834 break;
835 case CMD_CONV_NEW_IM:
836 is_chat = FALSE;
837 break;
838 }
839 } else {
840 break;
841 }
842 }
843 if (objc - argsused != 2) {
844 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
845 return TCL_ERROR;
846 }
847 if ((account = tcl_validate_account(objv[argsused++], interp)) == NULL)
848 return TCL_ERROR;
849 if (is_chat)
850 convo = PURPLE_CONVERSATION(purple_chat_conversation_new(account, Tcl_GetString(objv[argsused])));
851 else
852 convo = PURPLE_CONVERSATION(purple_im_conversation_new(account, Tcl_GetString(objv[argsused])));
853 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo));
854 break;
855 case CMD_CONV_WRITE:
856 if (objc != 6) {
857 Tcl_WrongNumArgs(interp, 2, objv, "conversation style from what");
858 return TCL_ERROR;
859 }
860 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
861 return TCL_ERROR;
862 if ((error = Tcl_GetIndexFromObj(interp, objv[3], styles, "style", 0, (int *)&style)) != TCL_OK)
863 return error;
864 from = Tcl_GetString(objv[4]);
865 what = Tcl_GetString(objv[5]);
866
867 switch (style) {
868 case CMD_CONV_WRITE_SEND:
869 pmsg = purple_message_new_outgoing(from, what, 0);
870 break;
871 case CMD_CONV_WRITE_RECV:
872 pmsg = purple_message_new_incoming(from, what, 0, 0);
873 break;
874 case CMD_CONV_WRITE_SYSTEM:
875 default:
876 pmsg = purple_message_new_system(what, 0);
877 break;
878 }
879 purple_conversation_write_message(convo, pmsg);
880 break;
881 case CMD_CONV_NAME:
882 if (objc != 3) {
883 Tcl_WrongNumArgs(interp, 2, objv, "conversation");
884 return TCL_ERROR;
885 }
886
887 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
888 return TCL_ERROR;
889 Tcl_SetObjResult(interp,
890 Tcl_NewStringObj((char *)purple_conversation_get_name(convo), -1));
891 break;
892 case CMD_CONV_TITLE:
893 if (objc != 3) {
894 Tcl_WrongNumArgs(interp, 2, objv, "conversation");
895 return TCL_ERROR;
896 }
897
898 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
899 return TCL_ERROR;
900 Tcl_SetObjResult(interp,
901 Tcl_NewStringObj((char *)purple_conversation_get_title(convo), -1));
902 break;
903 case CMD_CONV_SEND:
904 if (objc != 4) {
905 Tcl_WrongNumArgs(interp, 2, objv, "conversation message");
906 return TCL_ERROR;
907 }
908 if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
909 return TCL_ERROR;
910 what = Tcl_GetString(objv[3]);
911 purple_conversation_send(convo, what);
912 break;
913 }
914
915 return TCL_OK;
916 }
917
918 int tcl_cmd_core(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
919 {
920 const char *cmds[] = { "handle", "quit", NULL };
921 enum { CMD_CORE_HANDLE, CMD_CORE_QUIT } cmd;
922 int error;
923
924 if (objc < 2) {
925 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
926 return TCL_ERROR;
927 }
928
929 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
930 return error;
931
932 switch (cmd) {
933 case CMD_CORE_HANDLE:
934 if (objc != 2) {
935 Tcl_WrongNumArgs(interp, 2, objv, "");
936 return TCL_ERROR;
937 }
938 Tcl_SetObjResult(interp,
939 purple_tcl_ref_new(PurpleTclRefHandle,
940 purple_get_core()));
941 break;
942 case CMD_CORE_QUIT:
943 if (objc != 2) {
944 Tcl_WrongNumArgs(interp, 2, objv, "");
945 return TCL_ERROR;
946 }
947 purple_core_quit();
948 break;
949 }
950
951 return TCL_OK;
952 }
953
954 int tcl_cmd_debug(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
955 {
956 char *category, *message;
957 int lev;
958 const char *levels[] = { "-misc", "-info", "-warning", "-error", NULL };
959 PurpleDebugLevel levelind[] = { PURPLE_DEBUG_MISC, PURPLE_DEBUG_INFO, PURPLE_DEBUG_WARNING, PURPLE_DEBUG_ERROR };
960 int error;
961
962 if (objc != 4) {
963 Tcl_WrongNumArgs(interp, 1, objv, "level category message");
964 return TCL_ERROR;
965 }
966
967 error = Tcl_GetIndexFromObj(interp, objv[1], levels, "debug level", 0, &lev);
968 if (error != TCL_OK)
969 return error;
970
971 category = Tcl_GetString(objv[2]);
972 message = Tcl_GetString(objv[3]);
973
974 purple_debug(levelind[lev], category, "%s\n", message);
975
976 return TCL_OK;
977 }
978
979 int tcl_cmd_notify(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
980 {
981 int error, type;
982 const char *opts[] = { "-error", "-warning", "-info", NULL };
983 PurpleNotifyMsgType optind[] = { PURPLE_NOTIFY_MSG_ERROR, PURPLE_NOTIFY_MSG_WARNING, PURPLE_NOTIFY_MSG_INFO };
984 char *title, *msg1, *msg2;
985
986 if (objc < 4 || objc > 5) {
987 Tcl_WrongNumArgs(interp, 1, objv, "?type? title primary secondary");
988 return TCL_ERROR;
989 }
990
991 if (objc == 4) {
992 type = 1; /* Default to warning */
993 title = Tcl_GetString(objv[1]);
994 msg1 = Tcl_GetString(objv[2]);
995 msg2 = Tcl_GetString(objv[3]);
996 } else {
997 error = Tcl_GetIndexFromObj(interp, objv[1], opts, "message type", 0, &type);
998 if (error != TCL_OK)
999 return error;
1000 title = Tcl_GetString(objv[2]);
1001 msg1 = Tcl_GetString(objv[3]);
1002 msg2 = Tcl_GetString(objv[4]);
1003 }
1004
1005 purple_notify_message(_tcl_plugin, optind[type], title, msg1, msg2, NULL, NULL, NULL);
1006
1007 return TCL_OK;
1008 }
1009
1010 int tcl_cmd_plugins(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1011 {
1012 const char *cmds[] = { "handle", NULL };
1013 enum { CMD_PLUGINS_HANDLE } cmd;
1014 int error;
1015
1016 if (objc < 2) {
1017 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1018 return TCL_ERROR;
1019 }
1020
1021 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1022 return error;
1023
1024 switch (cmd) {
1025 case CMD_PLUGINS_HANDLE:
1026 if (objc != 2) {
1027 Tcl_WrongNumArgs(interp, 2, objv, "");
1028 return TCL_ERROR;
1029 }
1030 Tcl_SetObjResult(interp,
1031 purple_tcl_ref_new(PurpleTclRefHandle,
1032 purple_plugins_get_handle()));
1033 break;
1034 }
1035
1036 return TCL_OK;
1037 }
1038
1039 int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1040 {
1041 Tcl_Obj *list, *elem, **elems;
1042 const char *cmds[] = { "get", "set", "type", NULL };
1043 enum { CMD_PREFS_GET, CMD_PREFS_SET, CMD_PREFS_TYPE } cmd;
1044 /* char *types[] = { "none", "boolean", "int", "string", "stringlist", NULL }; */
1045 /* enum { TCL_PREFS_NONE, TCL_PREFS_BOOL, TCL_PREFS_INT, TCL_PREFS_STRING, TCL_PREFS_STRINGLIST } type; */
1046 PurplePrefType preftype;
1047 GList *cur;
1048 int error, intval, nelem, i;
1049
1050 if (objc < 2) {
1051 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1052 return TCL_ERROR;
1053 }
1054
1055 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1056 return error;
1057
1058 switch (cmd) {
1059 case CMD_PREFS_GET:
1060 if (objc != 3) {
1061 Tcl_WrongNumArgs(interp, 1, objv, "path");
1062 return TCL_ERROR;
1063 }
1064 preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
1065 switch (preftype) {
1066 case PURPLE_PREF_NONE:
1067 Tcl_SetObjResult(interp,
1068 Tcl_NewStringObj("pref type none", -1));
1069 return TCL_ERROR;
1070 break;
1071 case PURPLE_PREF_BOOLEAN:
1072 Tcl_SetObjResult(interp,
1073 Tcl_NewBooleanObj(
1074 purple_prefs_get_bool(Tcl_GetString(objv[2]))));
1075 break;
1076 case PURPLE_PREF_INT:
1077 Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_prefs_get_int(Tcl_GetString(objv[2]))));
1078 break;
1079 case PURPLE_PREF_STRING:
1080 Tcl_SetObjResult(interp,
1081 Tcl_NewStringObj((char *)purple_prefs_get_string(Tcl_GetString(objv[2])), -1));
1082 break;
1083 case PURPLE_PREF_STRING_LIST:
1084 cur = purple_prefs_get_string_list(Tcl_GetString(objv[2]));
1085 list = Tcl_NewListObj(0, NULL);
1086 while (cur != NULL) {
1087 elem = Tcl_NewStringObj((char *)cur->data, -1);
1088 Tcl_ListObjAppendElement(interp, list, elem);
1089 cur = g_list_next(cur);
1090 }
1091 Tcl_SetObjResult(interp, list);
1092 break;
1093 default:
1094 purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
1095 Tcl_SetObjResult(interp,
1096 Tcl_NewStringObj("unknown pref type", -1));
1097 return TCL_ERROR;
1098 }
1099 break;
1100 case CMD_PREFS_SET:
1101 if (objc != 4) {
1102 Tcl_WrongNumArgs(interp, 1, objv, "path value");
1103 return TCL_ERROR;
1104 }
1105 preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
1106 switch (preftype) {
1107 case PURPLE_PREF_NONE:
1108 Tcl_SetObjResult(interp,
1109 Tcl_NewStringObj("bad path or pref type none", -1));
1110 return TCL_ERROR;
1111 break;
1112 case PURPLE_PREF_BOOLEAN:
1113 if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &intval)) != TCL_OK)
1114 return error;
1115 purple_prefs_set_bool(Tcl_GetString(objv[2]), intval);
1116 break;
1117 case PURPLE_PREF_INT:
1118 if ((error = Tcl_GetIntFromObj(interp, objv[3], &intval)) != TCL_OK)
1119 return error;
1120 purple_prefs_set_int(Tcl_GetString(objv[2]), intval);
1121 break;
1122 case PURPLE_PREF_STRING:
1123 purple_prefs_set_string(Tcl_GetString(objv[2]), Tcl_GetString(objv[3]));
1124 break;
1125 case PURPLE_PREF_STRING_LIST:
1126 if ((error = Tcl_ListObjGetElements(interp, objv[3], &nelem, &elems)) != TCL_OK)
1127 return error;
1128 cur = NULL;
1129 for (i = 0; i < nelem; i++) {
1130 cur = g_list_append(cur, (gpointer)Tcl_GetString(elems[i]));
1131 }
1132 purple_prefs_set_string_list(Tcl_GetString(objv[2]), cur);
1133 g_list_free(cur);
1134 break;
1135 default:
1136 purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
1137 return TCL_ERROR;
1138 }
1139 break;
1140 case CMD_PREFS_TYPE:
1141 if (objc != 3) {
1142 Tcl_WrongNumArgs(interp, 1, objv, "path");
1143 return TCL_ERROR;
1144 }
1145 preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
1146 switch (preftype) {
1147 case PURPLE_PREF_NONE:
1148 Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
1149 break;
1150 case PURPLE_PREF_BOOLEAN:
1151 Tcl_SetObjResult(interp, Tcl_NewStringObj("boolean", -1));
1152 break;
1153 case PURPLE_PREF_INT:
1154 Tcl_SetObjResult(interp, Tcl_NewStringObj("int", -1));
1155 break;
1156 case PURPLE_PREF_STRING:
1157 Tcl_SetObjResult(interp, Tcl_NewStringObj("string", -1));
1158 break;
1159 case PURPLE_PREF_STRING_LIST:
1160 Tcl_SetObjResult(interp, Tcl_NewStringObj("stringlist", -1));
1161 break;
1162 default:
1163 purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
1164 Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown", -1));
1165 }
1166 break;
1167 }
1168
1169 return TCL_OK;
1170 }
1171
1172 int tcl_cmd_presence(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1173 {
1174 const char *cmds[] = { "account", "active_status", "available",
1175 "idle", "type", "login", "online", "status",
1176 "statuses", NULL };
1177 enum { CMD_PRESENCE_ACCOUNT, CMD_PRESENCE_ACTIVE_STATUS,
1178 CMD_PRESENCE_AVAILABLE, CMD_PRESENCE_IDLE, CMD_PRESENCE_TYPE,
1179 CMD_PRESENCE_LOGIN, CMD_PRESENCE_ONLINE,
1180 CMD_PRESENCE_STATUS, CMD_PRESENCE_STATUSES } cmd;
1181 Tcl_Obj *result;
1182 Tcl_Obj *list, *elem;
1183 PurplePresence *presence;
1184 GList *cur;
1185 int error, idle, idle_time, login_time;
1186
1187 if (objc < 2) {
1188 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1189 return TCL_ERROR;
1190 }
1191
1192 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1193 return error;
1194
1195 switch (cmd) {
1196 case CMD_PRESENCE_ACCOUNT:
1197 if (objc != 3) {
1198 Tcl_WrongNumArgs(interp, 2, objv, "presence");
1199 return TCL_ERROR;
1200 }
1201 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1202 return TCL_ERROR;
1203 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefAccount,
1204 purple_account_presence_get_account(PURPLE_ACCOUNT_PRESENCE(presence))));
1205 break;
1206 case CMD_PRESENCE_ACTIVE_STATUS:
1207 if (objc != 3 && objc != 4 && objc != 5) {
1208 Tcl_WrongNumArgs(interp, 2, objv, "presence [?status_id? | ?-primitive primitive?]");
1209 return TCL_ERROR;
1210 }
1211 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1212 return TCL_ERROR;
1213 if (objc == 3) {
1214 Tcl_SetObjResult(interp,
1215 purple_tcl_ref_new(PurpleTclRefStatus,
1216 purple_presence_get_active_status(presence)));
1217 } else if (objc == 4) {
1218 Tcl_SetObjResult(interp,
1219 Tcl_NewBooleanObj(
1220 purple_presence_is_status_active(presence,
1221 Tcl_GetString(objv[3]))));
1222 } else {
1223 PurpleStatusPrimitive primitive;
1224 if (strcmp(Tcl_GetString(objv[3]), "-primitive")) {
1225 result = Tcl_NewStringObj("bad option \"", -1);
1226 Tcl_AppendObjToObj(result, objv[3]);
1227 Tcl_AppendToObj(result,
1228 "\": should be -primitive", -1);
1229 Tcl_SetObjResult(interp,result);
1230 return TCL_ERROR;
1231 }
1232 primitive = purple_primitive_get_type_from_id(Tcl_GetString(objv[4]));
1233 if (primitive == PURPLE_STATUS_UNSET) {
1234 result = Tcl_NewStringObj("invalid primitive ", -1);
1235 Tcl_AppendObjToObj(result, objv[4]);
1236 Tcl_SetObjResult(interp,result);
1237 return TCL_ERROR;
1238 }
1239 Tcl_SetObjResult(interp,
1240 Tcl_NewBooleanObj(
1241 purple_presence_is_status_primitive_active(presence, primitive)));
1242 break;
1243 }
1244 break;
1245 case CMD_PRESENCE_AVAILABLE:
1246 if (objc != 3) {
1247 Tcl_WrongNumArgs(interp, 2, objv, "presence");
1248 return TCL_ERROR;
1249 }
1250 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1251 return TCL_ERROR;
1252 Tcl_SetObjResult(interp,
1253 Tcl_NewBooleanObj(purple_presence_is_available(presence)));
1254 break;
1255 case CMD_PRESENCE_TYPE:
1256 if (objc != 3) {
1257 Tcl_WrongNumArgs(interp, 2, objv, "presence");
1258 return TCL_ERROR;
1259 }
1260 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1261 return TCL_ERROR;
1262 if (PURPLE_IS_ACCOUNT_PRESENCE(presence))
1263 Tcl_SetObjResult(interp, Tcl_NewStringObj("account", -1));
1264 else if (PURPLE_IS_BUDDY_PRESENCE(presence))
1265 Tcl_SetObjResult(interp, Tcl_NewStringObj("buddy", -1));
1266 break;
1267 case CMD_PRESENCE_IDLE:
1268 if (objc < 3 || objc > 5) {
1269 Tcl_WrongNumArgs(interp, 2, objv, "presence ?idle? ?time?");
1270 return TCL_ERROR;
1271 }
1272 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1273 return TCL_ERROR;
1274 if (objc == 3) {
1275 if (purple_presence_is_idle(presence)) {
1276 idle_time = purple_presence_get_idle_time (presence);
1277 Tcl_SetObjResult(interp, Tcl_NewIntObj(idle_time));
1278 } else {
1279 result = Tcl_NewListObj(0, NULL);
1280 Tcl_SetObjResult(interp, result);
1281 }
1282 break;
1283 }
1284 if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &idle)) != TCL_OK)
1285 return TCL_ERROR;
1286 if (objc == 4) {
1287 purple_presence_set_idle(presence, idle, time(NULL));
1288 } else if (objc == 5) {
1289 if ((error = Tcl_GetIntFromObj(interp,
1290 objv[4],
1291 &idle_time)) != TCL_OK)
1292 return TCL_ERROR;
1293 purple_presence_set_idle(presence, idle, idle_time);
1294 }
1295 break;
1296 case CMD_PRESENCE_LOGIN:
1297 if (objc != 3 && objc != 4) {
1298 Tcl_WrongNumArgs(interp, 2, objv, "presence ?time?");
1299 return TCL_ERROR;
1300 }
1301 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1302 return TCL_ERROR;
1303 if (objc == 3) {
1304 Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_presence_get_login_time(presence)));
1305 } else {
1306 if ((error == Tcl_GetIntFromObj(interp,
1307 objv[3],
1308 &login_time)) != TCL_OK)
1309 return TCL_ERROR;
1310 purple_presence_set_login_time(presence, login_time);
1311 }
1312 break;
1313 case CMD_PRESENCE_ONLINE:
1314 if (objc != 3) {
1315 Tcl_WrongNumArgs(interp, 2, objv, "presence");
1316 return TCL_ERROR;
1317 }
1318 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1319 return TCL_ERROR;
1320 Tcl_SetObjResult(interp,
1321 Tcl_NewBooleanObj(
1322 purple_presence_is_online(presence)));
1323 break;
1324 case CMD_PRESENCE_STATUS:
1325 if (objc != 4) {
1326 Tcl_WrongNumArgs(interp, 2, objv, "presence status_id");
1327 return TCL_ERROR;
1328 }
1329 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1330 return TCL_ERROR;
1331 Tcl_SetObjResult(interp,
1332 purple_tcl_ref_new(PurpleTclRefStatus,
1333 purple_presence_get_status(presence,
1334 Tcl_GetString(objv[3]))));
1335 break;
1336 case CMD_PRESENCE_STATUSES:
1337 if (objc != 3) {
1338 Tcl_WrongNumArgs(interp, 2, objv, "presence");
1339 return TCL_ERROR;
1340 }
1341 if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
1342 return TCL_ERROR;
1343 list = Tcl_NewListObj(0, NULL);
1344 for (cur = purple_presence_get_statuses(presence); cur != NULL;
1345 cur = g_list_next(cur)) {
1346 elem = purple_tcl_ref_new(PurpleTclRefStatus, cur->data);
1347 Tcl_ListObjAppendElement(interp, list, elem);
1348 }
1349 Tcl_SetObjResult(interp, list);
1350 break;
1351 }
1352
1353 return TCL_OK;
1354 }
1355
1356 int tcl_cmd_savedstatus(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1357 {
1358 Tcl_Obj *result;
1359 const char *cmds[] = { "current", "handle", NULL };
1360 enum { CMD_SAVEDSTATUS_CURRENT, CMD_SAVEDSTATUS_HANDLE } cmd;
1361 int error;
1362 PurpleSavedStatus *saved_status;
1363
1364 if (objc < 2) {
1365 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1366 return TCL_ERROR;
1367 }
1368
1369 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1370 return error;
1371
1372 switch (cmd) {
1373 case CMD_SAVEDSTATUS_CURRENT:
1374 if (objc != 2) {
1375 Tcl_WrongNumArgs(interp, 2, objv, "");
1376 return TCL_ERROR;
1377 }
1378 if ((saved_status = purple_savedstatus_get_current()) == NULL)
1379 return TCL_ERROR;
1380 result = Tcl_NewListObj(0, NULL);
1381 Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(purple_savedstatus_get_title(saved_status), -1));
1382 Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(purple_savedstatus_get_primitive_type(saved_status)));
1383 Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(purple_savedstatus_get_message(saved_status), -1));
1384 Tcl_SetObjResult(interp,result);
1385 break;
1386 case CMD_SAVEDSTATUS_HANDLE:
1387 if (objc != 2) {
1388 Tcl_WrongNumArgs(interp, 2, objv, "");
1389 return TCL_ERROR;
1390 }
1391 Tcl_SetObjResult(interp,
1392 purple_tcl_ref_new(PurpleTclRefHandle,
1393 purple_savedstatuses_get_handle()));
1394 break;
1395 }
1396
1397 return TCL_OK;
1398 }
1399
1400 int tcl_cmd_send_im(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1401 {
1402 PurpleConnection *gc;
1403 char *who, *text;
1404
1405 if (objc != 4) {
1406 Tcl_WrongNumArgs(interp, 1, objv, "gc who text");
1407 return TCL_ERROR;
1408 }
1409
1410 if ((gc = tcl_validate_gc(objv[1], interp)) == NULL)
1411 return TCL_ERROR;
1412
1413 who = Tcl_GetString(objv[2]);
1414 text = Tcl_GetString(objv[3]);
1415
1416 purple_serv_send_im(gc, purple_message_new_outgoing(who, text, 0));
1417
1418 return TCL_OK;
1419 }
1420
1421 int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1422 {
1423 const char *cmds[] = { "connect", "disconnect", NULL };
1424 enum { CMD_SIGNAL_CONNECT, CMD_SIGNAL_DISCONNECT } cmd;
1425 struct tcl_signal_handler *handler;
1426 void *instance;
1427 int error;
1428
1429 if (objc < 2) {
1430 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1431 return TCL_ERROR;
1432 }
1433
1434 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1435 return error;
1436
1437 switch (cmd) {
1438 case CMD_SIGNAL_CONNECT:
1439 if (objc != 6) {
1440 Tcl_WrongNumArgs(interp, 2, objv, "instance signal args proc");
1441 return TCL_ERROR;
1442 }
1443 handler = g_new0(struct tcl_signal_handler, 1);
1444 if ((handler->instance = purple_tcl_ref_get(interp, objv[2],PurpleTclRefHandle)) == NULL) {
1445 g_free(handler);
1446 return error;
1447 }
1448 handler->signal = objv[3];
1449 Tcl_IncrRefCount(handler->signal);
1450 handler->args = objv[4];
1451 handler->proc = objv[5];
1452 handler->interp = interp;
1453 if (!tcl_signal_connect(handler)) {
1454 tcl_signal_handler_free(handler);
1455 Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
1456 } else {
1457 Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
1458 }
1459 break;
1460 case CMD_SIGNAL_DISCONNECT:
1461 if (objc != 4) {
1462 Tcl_WrongNumArgs(interp, 2, objv, "instance signal");
1463 return TCL_ERROR;
1464 }
1465 if ((instance = purple_tcl_ref_get(interp, objv[2],PurpleTclRefHandle)) == NULL)
1466 return error;
1467 tcl_signal_disconnect(instance, Tcl_GetString(objv[3]), interp);
1468 break;
1469 }
1470
1471 return TCL_OK;
1472 }
1473
1474 int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1475 {
1476 const char *cmds[] = { "attr", "type", NULL };
1477 enum { CMD_STATUS_ATTRIBUTE, CMD_STATUS_TYPE } cmd;
1478 PurpleStatus *status;
1479 PurpleStatusType *status_type;
1480 int error;
1481 # if (0)
1482 /* #if !(defined PURPLE_DISABLE_DEPRECATED) */
1483 PurpleValue *value;
1484 const char *attr;
1485 int v;
1486 #endif
1487
1488 if (objc < 2) {
1489 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1490 return TCL_ERROR;
1491 }
1492
1493 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1494 return error;
1495
1496 switch (cmd) {
1497 case CMD_STATUS_ATTRIBUTE:
1498 # if (0)
1499 /* #if !(defined PURPLE_DISABLE_DEPRECATED) */
1500 if (objc != 4 && objc != 5) {
1501 Tcl_WrongNumArgs(interp, 2, objv, "status attr_id ?value?");
1502 return TCL_ERROR;
1503 }
1504 if ((status = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatus)) == NULL)
1505 return TCL_ERROR;
1506 attr = Tcl_GetString(objv[3]);
1507 value = purple_status_get_attr_value(status, attr);
1508 if (value == NULL) {
1509 Tcl_SetObjResult(interp,
1510 Tcl_NewStringObj("no such attribute", -1));
1511 return TCL_ERROR;
1512 }
1513 switch (purple_value_get_type(value)) {
1514 case PURPLE_TYPE_BOOLEAN:
1515 if (objc == 4) {
1516 Tcl_SetObjResult(interp,
1517 Tcl_NewBooleanObj(purple_value_get_boolean(value)));
1518 } else {
1519 if ((error = Tcl_GetBooleanFromObj(interp, objv[4], &v)) != TCL_OK)
1520 return error;
1521 purple_status_set_attr_boolean(status, attr, v);
1522 }
1523 break;
1524 case PURPLE_TYPE_INT:
1525 if (objc == 4) {
1526 Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_value_get_int(value)));
1527 } else {
1528 if ((error = Tcl_GetIntFromObj(interp, objv[4], &v)) != TCL_OK)
1529 return error;
1530 purple_status_set_attr_int(status, attr, v );
1531 }
1532 break;
1533 case PURPLE_TYPE_STRING:
1534 if (objc == 4)
1535 Tcl_SetObjResult(interp,
1536 Tcl_NewStringObj(purple_value_get_string(value), -1));
1537 else
1538 purple_status_set_attr_string(status, attr, Tcl_GetString(objv[4]));
1539 break;
1540 default:
1541 Tcl_SetObjResult(interp,
1542 Tcl_NewStringObj("attribute has unknown type", -1));
1543 return TCL_ERROR;
1544 }
1545 #endif
1546 break;
1547 case CMD_STATUS_TYPE:
1548 if (objc != 3) {
1549 Tcl_WrongNumArgs(interp, 2, objv, "status");
1550 return TCL_ERROR;
1551 }
1552 if ((status = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatus)) == NULL)
1553 return TCL_ERROR;
1554 status_type = purple_status_get_status_type(status);
1555 Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefStatusType,
1556 status_type));
1557 break;
1558 }
1559
1560 return TCL_OK;
1561 }
1562
1563 int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1564 {
1565 const char *cmds[] = { "id", "name", NULL };
1566 enum { CMD_STATUS_ATTRIBUTE_ID, CMD_STATUS_ATTRIBUTE_NAME } cmd;
1567 PurpleStatusAttribute *attr;
1568 int error;
1569
1570 if (objc < 2) {
1571 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1572 return TCL_ERROR;
1573 }
1574
1575 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1576 return error;
1577
1578 switch (cmd) {
1579 case CMD_STATUS_ATTRIBUTE_ID:
1580 if (objc != 3) {
1581 Tcl_WrongNumArgs(interp, 2, objv, "attr");
1582 return TCL_ERROR;
1583 }
1584 if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL)
1585 return TCL_ERROR;
1586 Tcl_SetObjResult(interp,
1587 Tcl_NewStringObj(purple_status_attribute_get_id(attr), -1));
1588 break;
1589 case CMD_STATUS_ATTRIBUTE_NAME:
1590 if (objc != 3) {
1591 Tcl_WrongNumArgs(interp, 2, objv, "attr");
1592 return TCL_ERROR;
1593 }
1594 if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL)
1595 return TCL_ERROR;
1596 Tcl_SetObjResult(interp,
1597 Tcl_NewStringObj(purple_status_attribute_get_name(attr), -1));
1598 break;
1599 }
1600
1601 return TCL_OK;
1602 }
1603
1604 int tcl_cmd_status_type(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1605 {
1606 const char *cmds[] = { "attr", "attrs", "available", "exclusive", "id",
1607 "independent", "name",
1608 "primitive", "saveable", "user_settable",
1609 NULL };
1610 enum { CMD_STATUS_TYPE_ATTR, CMD_STATUS_TYPE_ATTRS,
1611 CMD_STATUS_TYPE_AVAILABLE, CMD_STATUS_TYPE_EXCLUSIVE,
1612 CMD_STATUS_TYPE_ID, CMD_STATUS_TYPE_INDEPENDENT,
1613 CMD_STATUS_TYPE_NAME,
1614 CMD_STATUS_TYPE_PRIMITIVE, CMD_STATUS_TYPE_SAVEABLE,
1615 CMD_STATUS_TYPE_USER_SETTABLE } cmd;
1616 PurpleStatusType *status_type;
1617 Tcl_Obj *list, *elem;
1618 GList *cur;
1619 int error;
1620
1621 if (objc < 2) {
1622 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
1623 return TCL_ERROR;
1624 }
1625
1626 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
1627 return error;
1628
1629 switch (cmd) {
1630 case CMD_STATUS_TYPE_AVAILABLE:
1631 if (objc != 3) {
1632 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1633 return TCL_ERROR;
1634 }
1635 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1636 return TCL_ERROR;
1637 Tcl_SetObjResult(interp,
1638 Tcl_NewBooleanObj(purple_status_type_is_available(status_type)));
1639 break;
1640 case CMD_STATUS_TYPE_ATTR:
1641 if (objc != 4) {
1642 Tcl_WrongNumArgs(interp, 2, objv, "statustype attr");
1643 return TCL_ERROR;
1644 }
1645 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1646 return TCL_ERROR;
1647 Tcl_SetObjResult(interp,
1648 purple_tcl_ref_new(PurpleTclRefStatusAttr,
1649 purple_status_type_get_attr(status_type,
1650 Tcl_GetStringFromObj(objv[3], NULL))));
1651 break;
1652 case CMD_STATUS_TYPE_ATTRS:
1653 if (objc != 3) {
1654 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1655 return TCL_ERROR;
1656 }
1657 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1658 return TCL_ERROR;
1659 list = Tcl_NewListObj(0, NULL);
1660 for (cur = purple_status_type_get_attrs(status_type);
1661 cur != NULL; cur = g_list_next(cur)) {
1662 elem = purple_tcl_ref_new(PurpleTclRefStatusAttr, cur->data);
1663 Tcl_ListObjAppendElement(interp, list, elem);
1664 }
1665 Tcl_SetObjResult(interp, list);
1666 break;
1667 case CMD_STATUS_TYPE_EXCLUSIVE:
1668 if (objc != 3) {
1669 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1670 return TCL_ERROR;
1671 }
1672 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1673 return TCL_ERROR;
1674 Tcl_SetObjResult(interp,
1675 Tcl_NewBooleanObj(purple_status_type_is_exclusive(status_type)));
1676 break;
1677 case CMD_STATUS_TYPE_ID:
1678 if (objc != 3) {
1679 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1680 return TCL_ERROR;
1681 }
1682 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1683 return TCL_ERROR;
1684 Tcl_SetObjResult(interp,
1685 Tcl_NewStringObj(purple_status_type_get_id(status_type), -1));
1686 break;
1687 case CMD_STATUS_TYPE_INDEPENDENT:
1688 if (objc != 3) {
1689 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1690 return TCL_ERROR;
1691 }
1692 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1693 return TCL_ERROR;
1694 Tcl_SetObjResult(interp,
1695 Tcl_NewBooleanObj(purple_status_type_is_independent(status_type)));
1696 break;
1697 case CMD_STATUS_TYPE_NAME:
1698 if (objc != 3) {
1699 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1700 return TCL_ERROR;
1701 }
1702 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1703 return TCL_ERROR;
1704 Tcl_SetObjResult(interp,
1705 Tcl_NewStringObj(purple_status_type_get_name(status_type), -1));
1706 break;
1707 case CMD_STATUS_TYPE_PRIMITIVE:
1708 if (objc != 3) {
1709 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1710 return TCL_ERROR;
1711 }
1712 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1713 return TCL_ERROR;
1714 Tcl_SetObjResult(interp,
1715 Tcl_NewStringObj(purple_primitive_get_id_from_type
1716 (purple_status_type_get_primitive(status_type)), -1));
1717 break;
1718 case CMD_STATUS_TYPE_SAVEABLE:
1719 if (objc != 3) {
1720 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1721 return TCL_ERROR;
1722 }
1723 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1724 return TCL_ERROR;
1725 Tcl_SetObjResult(interp,
1726 Tcl_NewBooleanObj(
1727 purple_status_type_is_saveable(status_type)));
1728 break;
1729 case CMD_STATUS_TYPE_USER_SETTABLE:
1730 if (objc != 3) {
1731 Tcl_WrongNumArgs(interp, 2, objv, "statustype");
1732 return TCL_ERROR;
1733 }
1734 if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
1735 return TCL_ERROR;
1736 Tcl_SetObjResult(interp,
1737 Tcl_NewBooleanObj(
1738 purple_status_type_is_user_settable(status_type)));
1739 break;
1740 }
1741
1742 return TCL_OK;
1743 }
1744
1745 static gboolean unload_self(gpointer data)
1746 {
1747 PurplePlugin *plugin = data;
1748 purple_plugin_unload(plugin);
1749 return FALSE;
1750 }
1751
1752 int tcl_cmd_unload(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
1753 {
1754 PurplePlugin *plugin;
1755 if (objc != 1) {
1756 Tcl_WrongNumArgs(interp, 1, objv, "");
1757 return TCL_ERROR;
1758 }
1759
1760 if ((plugin = tcl_interp_get_plugin(interp)) == NULL) {
1761 /* This isn't exactly OK, but heh. What do you do? */
1762 return TCL_OK;
1763 }
1764 /* We can't unload immediately, but we can unload at the first
1765 * known safe opportunity. */
1766 purple_timeout_add(0, unload_self, (gpointer)plugin);
1767
1768 return TCL_OK;
1769 }

mercurial