comparison plugins/tcl/tcl_cmds.c @ 6694:2d2f04c5c7d2

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