plugins/tcl/tcl_cmds.c

branch
gaim
changeset 20470
77693555855f
parent 13071
b98e72d4089a
parent 20469
b2836a24d81e
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
1 /**
2 * @file tcl_cmds.c Commands for the Gaim Tcl plugin bindings
3 *
4 * gaim
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <tcl.h>
24
25 #include "internal.h"
26 #include "conversation.h"
27 #include "connection.h"
28 #include "account.h"
29 #include "server.h"
30 #include "notify.h"
31 #include "blist.h"
32 #include "debug.h"
33 #include "prefs.h"
34 #include "core.h"
35
36 #include "tcl_gaim.h"
37
38 static gboolean tcl_validate_account(GaimAccount *account, Tcl_Interp *interp);
39 static gboolean tcl_validate_conversation(GaimConversation *convo, Tcl_Interp *interp);
40 static gboolean tcl_validate_gc(GaimConnection *gc);
41
42 static gboolean tcl_validate_account(GaimAccount *account, Tcl_Interp *interp)
43 {
44 GList *cur;
45 for (cur = gaim_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
46 if (account == cur->data)
47 return TRUE;
48 }
49 if (interp != NULL)
50 Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1);
51 return FALSE;
52 }
53
54 static gboolean tcl_validate_conversation(GaimConversation *convo, Tcl_Interp *interp)
55 {
56 GList *cur;
57
58 for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) {
59 if (convo == cur->data)
60 return TRUE;
61 }
62 if (interp != NULL)
63 Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1);
64 return FALSE;
65 }
66
67 static gboolean tcl_validate_gc(GaimConnection *gc)
68 {
69 GList *cur;
70 for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
71 if (gc == cur->data)
72 return TRUE;
73 }
74 return FALSE;
75 }
76
77 int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
78 {
79 Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem;
80 const char *cmds[] = { "alias", "connect", "connection", "disconnect", "find",
81 "handle", "isconnected", "list",
82 "protocol", "username", NULL };
83 enum { CMD_ACCOUNT_ALIAS, CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION,
84 CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_FIND, CMD_ACCOUNT_HANDLE,
85 CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST,
86 CMD_ACCOUNT_PROTOCOL, CMD_ACCOUNT_USERNAME } cmd;
87 const char *listopts[] = { "-all", "-online", NULL };
88 enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
89 const char *alias;
90 GList *cur;
91 GaimAccount *account;
92 int error;
93
94 if (objc < 2) {
95 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
96 return TCL_ERROR;
97 }
98
99 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
100 return error;
101
102 switch (cmd) {
103 case CMD_ACCOUNT_ALIAS:
104 if (objc != 3) {
105 Tcl_WrongNumArgs(interp, 2, objv, "account");
106 return TCL_ERROR;
107 }
108 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
109 if (error || !tcl_validate_account(account, interp))
110 return TCL_ERROR;
111 alias = gaim_account_get_alias(account);
112 Tcl_SetStringObj(result, alias ? (char *)alias : "", -1);
113 break;
114 case CMD_ACCOUNT_CONNECT:
115 if (objc != 3) {
116 Tcl_WrongNumArgs(interp, 2, objv, "account");
117 return TCL_ERROR;
118 }
119 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
120 if (error || !tcl_validate_account(account, interp))
121 return TCL_ERROR;
122 if (!gaim_account_is_connected(account))
123 gaim_account_connect(account);
124 Tcl_SetIntObj(result, (int)gaim_account_get_connection(account));
125 break;
126 case CMD_ACCOUNT_CONNECTION:
127 if (objc != 3) {
128 Tcl_WrongNumArgs(interp, 2, objv, "account");
129 return TCL_ERROR;
130 }
131 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
132 if (error || !tcl_validate_account(account, interp))
133 return TCL_ERROR;
134 Tcl_SetIntObj(result, (int)gaim_account_get_connection(account));
135 break;
136 case CMD_ACCOUNT_DISCONNECT:
137 if (objc != 3) {
138 Tcl_WrongNumArgs(interp, 2, objv, "account");
139 return TCL_ERROR;
140 }
141 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
142 if (error || !tcl_validate_account(account, interp))
143 return TCL_ERROR;
144 gaim_account_disconnect(account);
145 break;
146 case CMD_ACCOUNT_FIND:
147 if (objc != 4) {
148 Tcl_WrongNumArgs(interp, 2, objv, "username protocol");
149 return TCL_ERROR;
150 }
151 Tcl_SetIntObj(result, (int)gaim_accounts_find(Tcl_GetString(objv[2]),
152 Tcl_GetString(objv[3])));
153 break;
154 case CMD_ACCOUNT_HANDLE:
155 if (objc != 2) {
156 Tcl_WrongNumArgs(interp, 2, objv, "");
157 return TCL_ERROR;
158 }
159 Tcl_SetIntObj(result, (int)gaim_accounts_get_handle());
160 break;
161 case CMD_ACCOUNT_ISCONNECTED:
162 if (objc != 3) {
163 Tcl_WrongNumArgs(interp, 2, objv, "account");
164 return TCL_ERROR;
165 }
166 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
167 if (error || !tcl_validate_account(account, interp))
168 return TCL_ERROR;
169 Tcl_SetBooleanObj(result, gaim_account_is_connected(account));
170 break;
171 case CMD_ACCOUNT_LIST:
172 listopt = CMD_ACCOUNTLIST_ALL;
173 if (objc > 3) {
174 Tcl_WrongNumArgs(interp, 2, objv, "?option?");
175 return TCL_ERROR;
176 }
177 if (objc == 3) {
178 if ((error = Tcl_GetIndexFromObj(interp, objv[2], listopts, "option", 0, (int *)&listopt)) != TCL_OK)
179 return error;
180 }
181 list = Tcl_NewListObj(0, NULL);
182 for (cur = gaim_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
183 account = cur->data;
184 if (listopt == CMD_ACCOUNTLIST_ONLINE && !gaim_account_is_connected(account))
185 continue;
186 elem = Tcl_NewIntObj((int)account);
187 Tcl_ListObjAppendElement(interp, list, elem);
188 }
189 Tcl_SetObjResult(interp, list);
190 break;
191 case CMD_ACCOUNT_PROTOCOL:
192 if (objc != 3) {
193 Tcl_WrongNumArgs(interp, 2, objv, "account");
194 return TCL_ERROR;
195 }
196 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
197 if (error || !tcl_validate_account(account, interp))
198 return TCL_ERROR;
199 Tcl_SetStringObj(result, (char *)gaim_account_get_protocol_id(account), -1);
200 break;
201 case CMD_ACCOUNT_USERNAME:
202 if (objc != 3) {
203 Tcl_WrongNumArgs(interp, 2, objv, "account");
204 return TCL_ERROR;
205 }
206 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
207 if (error || !tcl_validate_account(account, interp))
208 return TCL_ERROR;
209 Tcl_SetStringObj(result, (char *)gaim_account_get_username(account), -1);
210 break;
211 }
212
213 return TCL_OK;
214 }
215
216 static GaimBlistNode *tcl_list_to_buddy(Tcl_Interp *interp, int count, Tcl_Obj **elems)
217 {
218 GaimBlistNode *node = NULL;
219 GaimAccount *account;
220 char *name;
221 char *type;
222
223 if (count < 3) {
224 Tcl_SetStringObj(Tcl_GetObjResult(interp), "list too short", -1);
225 return NULL;
226 }
227
228 type = Tcl_GetString(elems[0]);
229 name = Tcl_GetString(elems[1]);
230 if (Tcl_GetIntFromObj(interp, elems[2], (int *)&account) != TCL_OK)
231 return NULL;
232 if (!tcl_validate_account(account, interp))
233 return NULL;
234
235 if (!strcmp(type, "buddy")) {
236 node = (GaimBlistNode *)gaim_find_buddy(account, name);
237 } else if (!strcmp(type, "group")) {
238 node = (GaimBlistNode *)gaim_blist_find_chat(account, name);
239 }
240
241 return node;
242 }
243
244 int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
245 {
246 Tcl_Obj *list, *tclgroup, *tclgrouplist, *tclcontact, *tclcontactlist, *tclbud, **elems, *result;
247 const char *cmds[] = { "alias", "handle", "info", "list", NULL };
248 enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd;
249 GaimBuddyList *blist;
250 GaimBlistNode *node, *gnode, *bnode;
251 GaimAccount *account;
252 GaimBuddy *bud;
253 GaimChat *cnode;
254 int error, all = 0, count;
255
256 if (objc < 2) {
257 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
258 return TCL_ERROR;
259 }
260 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
261 return error;
262
263 result = Tcl_GetObjResult(interp);
264
265 switch (cmd) {
266 case CMD_BUDDY_ALIAS:
267 if (objc != 3) {
268 Tcl_WrongNumArgs(interp, 2, objv, "buddy");
269 return TCL_ERROR;
270 }
271 if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
272 return error;
273 if ((node = tcl_list_to_buddy(interp, count, elems)) == NULL)
274 return TCL_ERROR;
275 if (node->type == GAIM_BLIST_CHAT_NODE)
276 Tcl_SetStringObj(result, ((GaimChat *)node)->alias, -1);
277 else if (node->type == GAIM_BLIST_BUDDY_NODE)
278 Tcl_SetStringObj(result, (char *)gaim_buddy_get_alias((GaimBuddy *)node), -1);
279 return TCL_OK;
280 break;
281 case CMD_BUDDY_HANDLE:
282 if (objc != 2) {
283 Tcl_WrongNumArgs(interp, 2, objv, "");
284 return TCL_ERROR;
285 }
286 Tcl_SetIntObj(result, (int)gaim_blist_get_handle());
287 break;
288 case CMD_BUDDY_INFO:
289 if (objc != 3 && objc != 4) {
290 Tcl_WrongNumArgs(interp, 2, objv, "( buddy | account username )");
291 return TCL_ERROR;
292 }
293 if (objc == 3) {
294 if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
295 return error;
296 if (count < 3) {
297 Tcl_SetStringObj(result, "buddy too short", -1);
298 return TCL_ERROR;
299 }
300 if (strcmp("buddy", Tcl_GetString(elems[0]))) {
301 Tcl_SetStringObj(result, "invalid buddy", -1);
302 return TCL_ERROR;
303 }
304 if ((error = Tcl_GetIntFromObj(interp, elems[2], (int *)&account)) != TCL_OK)
305 return TCL_ERROR;
306 if (!tcl_validate_account(account, interp))
307 return TCL_ERROR;
308 serv_get_info(gaim_account_get_connection(account), Tcl_GetString(elems[1]));
309 } else {
310 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account)) != TCL_OK)
311 return error;
312 if (!tcl_validate_account(account, interp))
313 return TCL_ERROR;
314 serv_get_info(gaim_account_get_connection(account), Tcl_GetString(objv[3]));
315 }
316 break;
317 case CMD_BUDDY_LIST:
318 if (objc == 3) {
319 if (!strcmp("-all", Tcl_GetString(objv[2]))) {
320 all = 1;
321 } else {
322 Tcl_SetStringObj(result, "", -1);
323 Tcl_AppendStringsToObj(result, "unknown option: ", Tcl_GetString(objv[2]), NULL);
324 return TCL_ERROR;
325 }
326 }
327 list = Tcl_NewListObj(0, NULL);
328 blist = gaim_get_blist();
329 for (gnode = blist->root; gnode != NULL; gnode = gnode->next) {
330 tclgroup = Tcl_NewListObj(0, NULL);
331 Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj("group", -1));
332 Tcl_ListObjAppendElement(interp, tclgroup,
333 Tcl_NewStringObj(((GaimGroup *)gnode)->name, -1));
334 tclgrouplist = Tcl_NewListObj(0, NULL);
335 for (node = gnode->child; node != NULL; node = node->next) {
336 switch (node->type) {
337 case GAIM_BLIST_CONTACT_NODE:
338 tclcontact = Tcl_NewListObj(0, NULL);
339 Tcl_IncrRefCount(tclcontact);
340 Tcl_ListObjAppendElement(interp, tclcontact, Tcl_NewStringObj("contact", -1));
341 tclcontactlist = Tcl_NewListObj(0, NULL);
342 Tcl_IncrRefCount(tclcontactlist);
343 count = 0;
344 for (bnode = node->child; bnode != NULL; bnode = bnode ->next) {
345 if (bnode->type != GAIM_BLIST_BUDDY_NODE)
346 continue;
347 bud = (GaimBuddy *)bnode;
348 if (!all && !gaim_account_is_connected(bud->account))
349 continue;
350 count++;
351 tclbud = Tcl_NewListObj(0, NULL);
352 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("buddy", -1));
353 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(bud->name, -1));
354 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)bud->account));
355 Tcl_ListObjAppendElement(interp, tclcontactlist, tclbud);
356 }
357 if (count) {
358 Tcl_ListObjAppendElement(interp, tclcontact, tclcontactlist);
359 Tcl_ListObjAppendElement(interp, tclgrouplist, tclcontact);
360 }
361 Tcl_DecrRefCount(tclcontact);
362 Tcl_DecrRefCount(tclcontactlist);
363 break;
364 case GAIM_BLIST_CHAT_NODE:
365 cnode = (GaimChat *)node;
366 if (!all && !gaim_account_is_connected(cnode->account))
367 continue;
368 tclbud = Tcl_NewListObj(0, NULL);
369 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("chat", -1));
370 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(cnode->alias, -1));
371 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)cnode->account));
372 Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud);
373 break;
374 default:
375 gaim_debug(GAIM_DEBUG_WARNING, "tcl", "Unexpected buddy type %d", node->type);
376 continue;
377 }
378 }
379 Tcl_ListObjAppendElement(interp, tclgroup, tclgrouplist);
380 Tcl_ListObjAppendElement(interp, list, tclgroup);
381 }
382 Tcl_SetObjResult(interp, list);
383 break;
384 }
385
386 return TCL_OK;
387 }
388
389 int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
390 {
391 Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem;
392 const char *cmds[] = { "account", "displayname", "handle", "list", NULL };
393 enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd;
394 int error;
395 GList *cur;
396 GaimConnection *gc;
397
398 if (objc < 2) {
399 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
400 return TCL_ERROR;
401 }
402
403 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
404 return error;
405
406 switch (cmd) {
407 case CMD_CONN_ACCOUNT:
408 if (objc != 3) {
409 Tcl_WrongNumArgs(interp, 2, objv, "gc");
410 return TCL_ERROR;
411 }
412 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&gc);
413 if (error || !tcl_validate_gc(gc)) {
414 Tcl_SetStringObj(result, "invalid gc", -1);
415 return TCL_ERROR;
416 }
417 Tcl_SetIntObj(result, (int)gaim_connection_get_account(gc));
418 break;
419 case CMD_CONN_DISPLAYNAME:
420 if (objc != 3) {
421 Tcl_WrongNumArgs(interp, 2, objv, "gc");
422 return TCL_ERROR;
423 }
424 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&gc);
425 if (error || !tcl_validate_gc(gc)) {
426 Tcl_SetStringObj(result, "invalid gc", -1);
427 return TCL_ERROR;
428 }
429 Tcl_SetStringObj(result, (char *)gaim_connection_get_display_name(gc), -1);
430 break;
431 case CMD_CONN_HANDLE:
432 if (objc != 2) {
433 Tcl_WrongNumArgs(interp, 2, objv, "");
434 return TCL_ERROR;
435 }
436 Tcl_SetIntObj(result, (int)gaim_connections_get_handle());
437 break;
438 case CMD_CONN_LIST:
439 if (objc != 2) {
440 Tcl_WrongNumArgs(interp, 2, objv, "");
441 return TCL_ERROR;
442 }
443 list = Tcl_NewListObj(0, NULL);
444 for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
445 elem = Tcl_NewIntObj((int)cur->data);
446 Tcl_ListObjAppendElement(interp, list, elem);
447 }
448 Tcl_SetObjResult(interp, list);
449 break;
450 }
451
452 return TCL_OK;
453 }
454
455 int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
456 {
457 Tcl_Obj *list, *elem, *result = Tcl_GetObjResult(interp);
458 const char *cmds[] = { "find", "handle", "list", "new", "write", NULL };
459 enum { CMD_CONV_FIND, CMD_CONV_HANDLE, CMD_CONV_LIST, CMD_CONV_NEW, CMD_CONV_WRITE } cmd;
460 const char *styles[] = { "send", "recv", "system", NULL };
461 enum { CMD_CONV_WRITE_SEND, CMD_CONV_WRITE_RECV, CMD_CONV_WRITE_SYSTEM } style;
462 const char *newopts[] = { "-chat", "-im" };
463 enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt;
464 GaimConversation *convo;
465 GaimAccount *account;
466 GaimConversationType type;
467 GList *cur;
468 char *opt, *from, *what;
469 int error, argsused, flags = 0;
470
471 if (objc < 2) {
472 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
473 return TCL_ERROR;
474 }
475
476 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
477 return error;
478
479 switch (cmd) {
480 case CMD_CONV_FIND:
481 if (objc != 4) {
482 Tcl_WrongNumArgs(interp, 2, objv, "account name");
483 return TCL_ERROR;
484 }
485 account = NULL;
486 if ((error = Tcl_GetIntFromObj(interp, objv[2],
487 (int *)&account)) != TCL_OK)
488 return error;
489 if (!tcl_validate_account(account, interp))
490 return TCL_ERROR;
491 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY,
492 Tcl_GetString(objv[3]),
493 account);
494 Tcl_SetIntObj(result, (int)convo);
495 break;
496 case CMD_CONV_HANDLE:
497 if (objc != 2) {
498 Tcl_WrongNumArgs(interp, 2, objv, "");
499 return TCL_ERROR;
500 }
501 Tcl_SetIntObj(result, (int)gaim_conversations_get_handle());
502 break;
503 case CMD_CONV_LIST:
504 list = Tcl_NewListObj(0, NULL);
505 for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) {
506 elem = Tcl_NewIntObj((int)cur->data);
507 Tcl_ListObjAppendElement(interp, list, elem);
508 }
509 Tcl_SetObjResult(interp, list);
510 break;
511 case CMD_CONV_NEW:
512 if (objc < 4) {
513 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
514 return TCL_ERROR;
515 }
516 argsused = 2;
517 type = GAIM_CONV_TYPE_IM;
518 while (argsused < objc) {
519 opt = Tcl_GetString(objv[argsused]);
520 if (*opt == '-') {
521 if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], newopts,
522 "option", 0, (int *)&newopt)) != TCL_OK)
523 return error;
524 argsused++;
525 switch (newopt) {
526 case CMD_CONV_NEW_CHAT:
527 type = GAIM_CONV_TYPE_CHAT;
528 break;
529 case CMD_CONV_NEW_IM:
530 type = GAIM_CONV_TYPE_IM;
531 break;
532 }
533 } else {
534 break;
535 }
536 }
537 if (objc - argsused != 2) {
538 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
539 return TCL_ERROR;
540 }
541 if ((error = Tcl_GetIntFromObj(interp, objv[argsused++], (int *)&account)) != TCL_OK)
542 return error;
543 if (!tcl_validate_account(account, interp))
544 return TCL_ERROR;
545 convo = gaim_conversation_new(type, account, Tcl_GetString(objv[argsused]));
546 Tcl_SetIntObj(result, (int)convo);
547 break;
548 case CMD_CONV_WRITE:
549 if (objc != 6) {
550 Tcl_WrongNumArgs(interp, 2, objv, "conversation style from what");
551 return TCL_ERROR;
552 }
553 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&convo)) != TCL_OK)
554 return error;
555 if ((error = Tcl_GetIndexFromObj(interp, objv[3], styles, "style", 0, (int *)&style)) != TCL_OK)
556 return error;
557 if (!tcl_validate_conversation(convo, interp))
558 return TCL_ERROR;
559 from = Tcl_GetString(objv[4]);
560 what = Tcl_GetString(objv[5]);
561
562 switch (style) {
563 case CMD_CONV_WRITE_SEND:
564 flags = GAIM_MESSAGE_SEND;
565 break;
566 case CMD_CONV_WRITE_RECV:
567 flags = GAIM_MESSAGE_RECV;
568 break;
569 case CMD_CONV_WRITE_SYSTEM:
570 flags = GAIM_MESSAGE_SYSTEM;
571 break;
572 }
573 if (gaim_conversation_get_type(convo) == GAIM_CONV_TYPE_CHAT)
574 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), from, what, flags, time(NULL));
575 else
576 gaim_conv_im_write(GAIM_CONV_IM(convo), from, what, flags, time(NULL));
577 break;
578 }
579
580 return TCL_OK;
581 }
582
583 int tcl_cmd_core(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
584 {
585 Tcl_Obj *result = Tcl_GetObjResult(interp);
586 const char *cmds[] = { "handle", "quit", NULL };
587 enum { CMD_CORE_HANDLE, CMD_CORE_QUIT } cmd;
588 int error;
589
590 if (objc < 2) {
591 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
592 return TCL_ERROR;
593 }
594
595 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
596 return error;
597
598 switch (cmd) {
599 case CMD_CORE_HANDLE:
600 if (objc != 2) {
601 Tcl_WrongNumArgs(interp, 2, objv, "");
602 return TCL_ERROR;
603 }
604 Tcl_SetIntObj(result, (int)gaim_get_core());
605 break;
606 case CMD_CORE_QUIT:
607 if (objc != 2) {
608 Tcl_WrongNumArgs(interp, 2, objv, "");
609 return TCL_ERROR;
610 }
611 gaim_core_quit();
612 break;
613 }
614
615 return TCL_OK;
616 }
617
618 int tcl_cmd_debug(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
619 {
620 char *category, *message;
621 int lev;
622 const char *levels[] = { "-misc", "-info", "-warning", "-error", NULL };
623 GaimDebugLevel levelind[] = { GAIM_DEBUG_MISC, GAIM_DEBUG_INFO, GAIM_DEBUG_WARNING, GAIM_DEBUG_ERROR };
624 int error;
625
626 if (objc != 4) {
627 Tcl_WrongNumArgs(interp, 1, objv, "level category message");
628 return TCL_ERROR;
629 }
630
631 error = Tcl_GetIndexFromObj(interp, objv[1], levels, "debug level", 0, &lev);
632 if (error != TCL_OK)
633 return error;
634
635 category = Tcl_GetString(objv[2]);
636 message = Tcl_GetString(objv[3]);
637
638 gaim_debug(levelind[lev], category, "%s\n", message);
639
640 return TCL_OK;
641 }
642
643 int tcl_cmd_notify(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
644 {
645 int error, type;
646 const char *opts[] = { "-error", "-warning", "-info", NULL };
647 GaimNotifyMsgType optind[] = { GAIM_NOTIFY_MSG_ERROR, GAIM_NOTIFY_MSG_WARNING, GAIM_NOTIFY_MSG_INFO };
648 char *title, *msg1, *msg2;
649
650 if (objc < 4 || objc > 5) {
651 Tcl_WrongNumArgs(interp, 1, objv, "?type? title primary secondary");
652 return TCL_ERROR;
653 }
654
655 if (objc == 4) {
656 title = Tcl_GetString(objv[1]);
657 msg1 = Tcl_GetString(objv[2]);
658 msg2 = Tcl_GetString(objv[3]);
659 } else {
660 error = Tcl_GetIndexFromObj(interp, objv[1], opts, "message type", 0, &type);
661 if (error != TCL_OK)
662 return error;
663 title = Tcl_GetString(objv[2]);
664 msg1 = Tcl_GetString(objv[3]);
665 msg2 = Tcl_GetString(objv[4]);
666 }
667
668 gaim_notify_message(_tcl_plugin, optind[type], title, msg1, msg2, NULL, NULL);
669
670 return TCL_OK;
671 }
672
673 int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
674 {
675 Tcl_Obj *result, *list, *elem, **elems;
676 const char *cmds[] = { "get", "set", "type", NULL };
677 enum { CMD_PREFS_GET, CMD_PREFS_SET, CMD_PREFS_TYPE } cmd;
678 /* char *types[] = { "none", "boolean", "int", "string", "stringlist", NULL }; */
679 /* enum { TCL_PREFS_NONE, TCL_PREFS_BOOL, TCL_PREFS_INT, TCL_PREFS_STRING, TCL_PREFS_STRINGLIST } type; */
680 GaimPrefType preftype;
681 GList *cur;
682 int error, intval, nelem, i;
683
684 if (objc < 2) {
685 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
686 return TCL_ERROR;
687 }
688
689 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
690 return error;
691
692 result = Tcl_GetObjResult(interp);
693 switch (cmd) {
694 case CMD_PREFS_GET:
695 if (objc != 3) {
696 Tcl_WrongNumArgs(interp, 1, objv, "path");
697 return TCL_ERROR;
698 }
699 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
700 switch (preftype) {
701 case GAIM_PREF_NONE:
702 Tcl_SetStringObj(result, "pref type none", -1);
703 return TCL_ERROR;
704 break;
705 case GAIM_PREF_BOOLEAN:
706 Tcl_SetBooleanObj(result, gaim_prefs_get_bool(Tcl_GetString(objv[2])));
707 break;
708 case GAIM_PREF_INT:
709 Tcl_SetIntObj(result, gaim_prefs_get_int(Tcl_GetString(objv[2])));
710 break;
711 case GAIM_PREF_STRING:
712 Tcl_SetStringObj(result, (char *)gaim_prefs_get_string(Tcl_GetString(objv[2])), -1);
713 break;
714 case GAIM_PREF_STRING_LIST:
715 cur = gaim_prefs_get_string_list(Tcl_GetString(objv[2]));
716 list = Tcl_NewListObj(0, NULL);
717 while (cur != NULL) {
718 elem = Tcl_NewStringObj((char *)cur->data, -1);
719 Tcl_ListObjAppendElement(interp, list, elem);
720 cur = g_list_next(cur);
721 }
722 Tcl_SetObjResult(interp, list);
723 break;
724 default:
725 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
726 Tcl_SetStringObj(result, "unknown pref type", -1);
727 return TCL_ERROR;
728 }
729 break;
730 case CMD_PREFS_SET:
731 if (objc != 4) {
732 Tcl_WrongNumArgs(interp, 1, objv, "path value");
733 return TCL_ERROR;
734 }
735 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
736 switch (preftype) {
737 case GAIM_PREF_NONE:
738 Tcl_SetStringObj(result, "bad path or pref type none", -1);
739 return TCL_ERROR;
740 break;
741 case GAIM_PREF_BOOLEAN:
742 if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &intval)) != TCL_OK)
743 return error;
744 gaim_prefs_set_bool(Tcl_GetString(objv[2]), intval);
745 break;
746 case GAIM_PREF_INT:
747 if ((error = Tcl_GetIntFromObj(interp, objv[3], &intval)) != TCL_OK)
748 return error;
749 gaim_prefs_set_int(Tcl_GetString(objv[2]), intval);
750 break;
751 case GAIM_PREF_STRING:
752 gaim_prefs_set_string(Tcl_GetString(objv[2]), Tcl_GetString(objv[3]));
753 break;
754 case GAIM_PREF_STRING_LIST:
755 if ((error = Tcl_ListObjGetElements(interp, objv[3], &nelem, &elems)) != TCL_OK)
756 return error;
757 cur = NULL;
758 for (i = 0; i < nelem; i++) {
759 cur = g_list_append(cur, (gpointer)Tcl_GetString(elems[i]));
760 }
761 gaim_prefs_set_string_list(Tcl_GetString(objv[2]), cur);
762 g_list_free(cur);
763 break;
764 default:
765 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
766 return TCL_ERROR;
767 }
768 break;
769 case CMD_PREFS_TYPE:
770 if (objc != 3) {
771 Tcl_WrongNumArgs(interp, 1, objv, "path");
772 return TCL_ERROR;
773 }
774 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
775 switch (preftype) {
776 case GAIM_PREF_NONE:
777 Tcl_SetStringObj(result, "none", -1);
778 break;
779 case GAIM_PREF_BOOLEAN:
780 Tcl_SetStringObj(result, "boolean", -1);
781 break;
782 case GAIM_PREF_INT:
783 Tcl_SetStringObj(result, "int", -1);
784 break;
785 case GAIM_PREF_STRING:
786 Tcl_SetStringObj(result, "string", -1);
787 break;
788 case GAIM_PREF_STRING_LIST:
789 Tcl_SetStringObj(result, "stringlist", -1);
790 break;
791 default:
792 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
793 Tcl_SetStringObj(result, "unknown", -1);
794 }
795 break;
796 }
797
798 return TCL_OK;
799 }
800
801 int tcl_cmd_send_im(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
802 {
803 GaimConnection *gc;
804 char *who, *text;
805 int error;
806 Tcl_Obj *result;
807
808 if (objc != 4) {
809 Tcl_WrongNumArgs(interp, 1, objv, "gc who text");
810 return TCL_ERROR;
811 }
812
813 if ((error = Tcl_GetIntFromObj(interp, objv[1], (int *)&gc)) != TCL_OK)
814 return error;
815 if (!tcl_validate_gc(gc)) {
816 result = Tcl_GetObjResult(interp);
817 Tcl_SetStringObj(result, "invalid gc", -1);
818 return TCL_ERROR;
819 }
820
821 who = Tcl_GetString(objv[2]);
822 text = Tcl_GetString(objv[3]);
823
824 serv_send_im(gc, who, text, 0);
825
826 return TCL_OK;
827 }
828
829 int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
830 {
831 const char *cmds[] = { "connect", "disconnect", NULL };
832 enum { CMD_SIGNAL_CONNECT, CMD_SIGNAL_DISCONNECT } cmd;
833 struct tcl_signal_handler *handler;
834 Tcl_Obj *result = Tcl_GetObjResult(interp);
835 void *instance;
836 int error;
837
838 if (objc < 2) {
839 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
840 return TCL_ERROR;
841 }
842
843 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
844 return error;
845
846 switch (cmd) {
847 case CMD_SIGNAL_CONNECT:
848 if (objc != 6) {
849 Tcl_WrongNumArgs(interp, 2, objv, "instance signal args proc");
850 return TCL_ERROR;
851 }
852 handler = g_new0(struct tcl_signal_handler, 1);
853 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&handler->instance)) != TCL_OK) {
854 g_free(handler);
855 return error;
856 }
857 handler->signal = objv[3];
858 handler->args = objv[4];
859 handler->proc = objv[5];
860 handler->interp = interp;
861 if (!tcl_signal_connect(handler)) {
862 tcl_signal_handler_free(handler);
863 Tcl_SetIntObj(result, 1);
864 } else {
865 Tcl_SetIntObj(result, 0);
866 }
867 break;
868 case CMD_SIGNAL_DISCONNECT:
869 if (objc != 4) {
870 Tcl_WrongNumArgs(interp, 2, objv, "signal");
871 return TCL_ERROR;
872 }
873 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&instance)) != TCL_OK)
874 return error;
875 tcl_signal_disconnect(instance, Tcl_GetString(objv[3]), interp);
876 break;
877 }
878
879 return TCL_OK;
880 }
881
882 static gboolean unload_self(gpointer data)
883 {
884 GaimPlugin *plugin = data;
885 gaim_plugin_unload(plugin);
886 return FALSE;
887 }
888
889 int tcl_cmd_unload(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
890 {
891 GaimPlugin *plugin;
892 if (objc != 1) {
893 Tcl_WrongNumArgs(interp, 1, objv, "");
894 return TCL_ERROR;
895 }
896
897 if ((plugin = tcl_interp_get_plugin(interp)) == NULL) {
898 /* This isn't exactly OK, but heh. What do you do? */
899 return TCL_OK;
900 }
901 /* We can't unload immediately, but we can unload at the first
902 * known safe opportunity. */
903 g_idle_add(unload_self, (gpointer)plugin);
904
905 return TCL_OK;
906 }

mercurial