6694
|
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 }
|