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"
|
6700
|
31 #include "blist.h"
|
6694
|
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_gc(GaimConnection *gc);
|
|
40
|
|
41 static gboolean tcl_validate_account(GaimAccount *account, Tcl_Interp *interp)
|
|
42 {
|
|
43 GList *cur;
|
|
44 for (cur = gaim_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
|
|
45 if (account == cur->data)
|
|
46 return TRUE;
|
|
47 }
|
|
48 if (interp != NULL)
|
|
49 Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1);
|
|
50 return FALSE;
|
|
51 }
|
|
52
|
|
53 static gboolean tcl_validate_conversation(GaimConversation *convo, Tcl_Interp *interp)
|
|
54 {
|
|
55 GList *cur;
|
|
56
|
|
57 for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) {
|
|
58 if (convo == cur->data)
|
|
59 return TRUE;
|
|
60 }
|
|
61 if (interp != NULL)
|
|
62 Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1);
|
|
63 return FALSE;
|
|
64 }
|
|
65
|
|
66 static gboolean tcl_validate_gc(GaimConnection *gc)
|
|
67 {
|
|
68 GList *cur;
|
|
69 for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
|
|
70 if (gc == cur->data)
|
|
71 return TRUE;
|
|
72 }
|
|
73 return FALSE;
|
|
74 }
|
|
75
|
|
76 int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
77 {
|
|
78 Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem;
|
|
79 char *cmds[] = { "alias", "connect", "connection", "disconnect", "find",
|
|
80 "handle", "isconnected", "list", "protocol", "username",
|
|
81 NULL };
|
|
82 enum { CMD_ACCOUNT_ALIAS, CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION,
|
|
83 CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_FIND, CMD_ACCOUNT_HANDLE,
|
|
84 CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST, CMD_ACCOUNT_PROTOCOL,
|
|
85 CMD_ACCOUNT_USERNAME } cmd;
|
|
86 char *listopts[] = { "-all", "-online", NULL };
|
|
87 enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
|
|
88 const char *alias;
|
|
89 GList *cur;
|
|
90 GaimAccount *account;
|
|
91 int error;
|
|
92
|
|
93 if (objc < 2) {
|
|
94 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
95 return TCL_ERROR;
|
|
96 }
|
|
97
|
|
98 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
99 return error;
|
|
100
|
|
101 switch (cmd) {
|
|
102 case CMD_ACCOUNT_ALIAS:
|
|
103 if (objc != 3) {
|
|
104 Tcl_WrongNumArgs(interp, 2, objv, "account");
|
|
105 return TCL_ERROR;
|
|
106 }
|
|
107 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
|
|
108 if (error || !tcl_validate_account(account, interp))
|
|
109 return TCL_ERROR;
|
|
110 alias = gaim_account_get_alias(account);
|
|
111 Tcl_SetStringObj(result, alias ? (char *)alias : "", -1);
|
|
112 break;
|
|
113 case CMD_ACCOUNT_CONNECT:
|
|
114 if (objc != 3) {
|
|
115 Tcl_WrongNumArgs(interp, 2, objv, "account");
|
|
116 return TCL_ERROR;
|
|
117 }
|
|
118 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
|
|
119 if (error || !tcl_validate_account(account, interp))
|
|
120 return TCL_ERROR;
|
|
121 if (gaim_account_is_connected(account))
|
|
122 Tcl_SetIntObj(result, (int)gaim_account_get_connection(account));
|
|
123 else
|
|
124 Tcl_SetIntObj(result, (int)gaim_account_connect(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_with_prpl_id(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, *tclbud, **elems, *result;
|
|
247 char *cmds[] = { "alias", "handle", "info", "list", NULL };
|
|
248 enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd;
|
|
249 struct gaim_buddy_list *blist;
|
|
250 GaimBlistNode *node, *gnode;
|
|
251 GaimAccount *account;
|
6700
|
252 GaimBuddy *bnode;
|
|
253 GaimBlistChat *cnode;
|
6694
|
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)
|
6700
|
276 Tcl_SetStringObj(result, ((GaimBlistChat *)node)->alias, -1);
|
6694
|
277 else if (node->type == GAIM_BLIST_BUDDY_NODE)
|
6700
|
278 Tcl_SetStringObj(result, (char *)gaim_get_buddy_alias((GaimBuddy *)node), -1);
|
6694
|
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,
|
6700
|
333 Tcl_NewStringObj(((GaimGroup *)gnode)->name, -1));
|
6694
|
334 tclgrouplist = Tcl_NewListObj(0, NULL);
|
|
335 for (node = gnode->child; node != NULL; node = node->next) {
|
|
336 switch (node->type) {
|
|
337 case GAIM_BLIST_BUDDY_NODE:
|
6700
|
338 bnode = (GaimBuddy *)node;
|
6694
|
339 if (!all && !gaim_account_is_connected(bnode->account))
|
|
340 continue;
|
|
341 tclbud = Tcl_NewListObj(0, NULL);
|
|
342 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("buddy", -1));
|
|
343 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(bnode->name, -1));
|
|
344 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)bnode->account));
|
|
345 break;
|
|
346 case GAIM_BLIST_CHAT_NODE:
|
6700
|
347 cnode = (GaimBlistChat *)node;
|
6694
|
348 if (!all && !gaim_account_is_connected(cnode->account))
|
|
349 continue;
|
|
350 tclbud = Tcl_NewListObj(0, NULL);
|
|
351 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("chat", -1));
|
|
352 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(cnode->alias, -1));
|
|
353 Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)cnode->account));
|
|
354 break;
|
|
355 default:
|
|
356 continue;
|
|
357 }
|
|
358 Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud);
|
|
359 }
|
|
360 Tcl_ListObjAppendElement(interp, tclgroup, tclgrouplist);
|
|
361 Tcl_ListObjAppendElement(interp, list, tclgroup);
|
|
362 }
|
|
363 Tcl_SetObjResult(interp, list);
|
|
364 break;
|
|
365 }
|
|
366
|
|
367 return TCL_OK;
|
|
368 }
|
|
369
|
|
370 int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
371 {
|
|
372 Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem;
|
|
373 char *cmds[] = { "account", "handle", "list", NULL };
|
|
374 enum { CMD_CONN_ACCOUNT, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd;
|
|
375 int error;
|
|
376 GList *cur;
|
|
377 GaimConnection *gc;
|
|
378
|
|
379 if (objc < 2) {
|
|
380 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
381 return TCL_ERROR;
|
|
382 }
|
|
383
|
|
384 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
385 return error;
|
|
386
|
|
387 switch (cmd) {
|
|
388 case CMD_CONN_ACCOUNT:
|
|
389 if (objc != 3) {
|
|
390 Tcl_WrongNumArgs(interp, 2, objv, _("gc"));
|
|
391 return TCL_ERROR;
|
|
392 }
|
|
393 error = Tcl_GetIntFromObj(interp, objv[2], (int *)&gc);
|
|
394 if (error || !tcl_validate_gc(gc)) {
|
|
395 Tcl_SetStringObj(result, "invalid gc", -1);
|
|
396 return TCL_ERROR;
|
|
397 }
|
|
398 Tcl_SetIntObj(result, (int)gaim_connection_get_account(gc));
|
|
399 break;
|
|
400 case CMD_CONN_HANDLE:
|
|
401 if (objc != 2) {
|
|
402 Tcl_WrongNumArgs(interp, 2, objv, "");
|
|
403 return TCL_ERROR;
|
|
404 }
|
|
405 Tcl_SetIntObj(result, (int)gaim_connections_get_handle());
|
|
406 break;
|
|
407 case CMD_CONN_LIST:
|
|
408 if (objc != 2) {
|
|
409 Tcl_WrongNumArgs(interp, 2, objv, "");
|
|
410 return TCL_ERROR;
|
|
411 }
|
|
412 list = Tcl_NewListObj(0, NULL);
|
|
413 for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
|
|
414 elem = Tcl_NewIntObj((int)cur->data);
|
|
415 Tcl_ListObjAppendElement(interp, list, elem);
|
|
416 }
|
|
417 Tcl_SetObjResult(interp, list);
|
|
418 break;
|
|
419 }
|
|
420
|
|
421 return TCL_OK;
|
|
422 }
|
|
423
|
|
424 int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
425 {
|
|
426 Tcl_Obj *list, *elem, *result = Tcl_GetObjResult(interp);
|
|
427 char *cmds[] = { "find", "handle", "list", "new", "write", NULL };
|
|
428 enum { CMD_CONV_FIND, CMD_CONV_HANDLE, CMD_CONV_LIST, CMD_CONV_NEW, CMD_CONV_WRITE } cmd;
|
|
429 char *styles[] = { "send", "recv", "system", NULL };
|
|
430 enum { CMD_CONV_WRITE_SEND, CMD_CONV_WRITE_RECV, CMD_CONV_WRITE_SYSTEM } style;
|
|
431 char *findopts[] = { "-account", NULL };
|
|
432 enum { CMD_CONV_FIND_ACCOUNT } findopt;
|
|
433 char *newopts[] = { "-chat", "-im" };
|
|
434 enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt;
|
|
435 GaimConversation *convo;
|
|
436 GaimAccount *account;
|
|
437 GaimConversationType type;
|
|
438 GList *cur;
|
|
439 char *opt, *from, *what;
|
|
440 int error, argsused, flags;
|
|
441
|
|
442 if (objc < 2) {
|
|
443 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
444 return TCL_ERROR;
|
|
445 }
|
|
446
|
|
447 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
448 return error;
|
|
449
|
|
450 switch (cmd) {
|
|
451 case CMD_CONV_FIND:
|
|
452 if (objc < 3) {
|
|
453 Tcl_WrongNumArgs(interp, 2, objv, "?options? name");
|
|
454 return TCL_ERROR;
|
|
455 }
|
|
456 argsused = 2;
|
|
457 account = NULL;
|
|
458 while (argsused < objc) {
|
|
459 opt = Tcl_GetString(objv[argsused]);
|
|
460 if (*opt == '-') {
|
|
461 if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], findopts,
|
|
462 "option", 0, (int *)&findopt)) != TCL_OK)
|
|
463 return error;
|
|
464 argsused++;
|
|
465 switch (findopt) {
|
|
466 case CMD_CONV_FIND_ACCOUNT:
|
|
467 if (argsused == objc - 1) {
|
|
468 Tcl_SetStringObj(result, "-account requires an argument", -1);
|
|
469 return TCL_ERROR;
|
|
470 }
|
|
471 if ((error = Tcl_GetIntFromObj(interp, objv[argsused],
|
|
472 (int *)&account)) != TCL_OK)
|
|
473 return error;
|
|
474 if (!tcl_validate_account(account, interp))
|
|
475 return TCL_ERROR;
|
|
476 argsused++;
|
|
477 break;
|
|
478 }
|
|
479 } else {
|
|
480 break;
|
|
481 }
|
|
482 }
|
|
483 if (objc - argsused != 1) {
|
|
484 Tcl_WrongNumArgs(interp, 2, objv, "?options? name");
|
|
485 return error;
|
|
486 }
|
|
487 if (account != NULL) {
|
|
488 convo = gaim_find_conversation_with_account(Tcl_GetString(objv[argsused]), account);
|
|
489 } else {
|
|
490 convo = gaim_find_conversation(Tcl_GetString(objv[argsused]));
|
|
491 }
|
|
492 Tcl_SetIntObj(result, (int)convo);
|
|
493 break;
|
|
494 case CMD_CONV_HANDLE:
|
|
495 if (objc != 2) {
|
|
496 Tcl_WrongNumArgs(interp, 2, objv, "");
|
|
497 return TCL_ERROR;
|
|
498 }
|
|
499 Tcl_SetIntObj(result, (int)gaim_conversations_get_handle());
|
|
500 break;
|
|
501 case CMD_CONV_LIST:
|
|
502 list = Tcl_NewListObj(0, NULL);
|
|
503 for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) {
|
|
504 elem = Tcl_NewIntObj((int)cur->data);
|
|
505 Tcl_ListObjAppendElement(interp, list, elem);
|
|
506 }
|
|
507 Tcl_SetObjResult(interp, list);
|
|
508 break;
|
|
509 case CMD_CONV_NEW:
|
|
510 if (objc < 4) {
|
|
511 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
|
|
512 return TCL_ERROR;
|
|
513 }
|
|
514 argsused = 2;
|
|
515 type = GAIM_CONV_IM;
|
|
516 while (argsused < objc) {
|
|
517 opt = Tcl_GetString(objv[argsused]);
|
|
518 if (*opt == '-') {
|
|
519 if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], newopts,
|
|
520 "option", 0, (int *)&newopt)) != TCL_OK)
|
|
521 return error;
|
|
522 argsused++;
|
|
523 switch (newopt) {
|
|
524 case CMD_CONV_NEW_CHAT:
|
|
525 type = GAIM_CONV_CHAT;
|
|
526 break;
|
|
527 case CMD_CONV_NEW_IM:
|
|
528 type = GAIM_CONV_IM;
|
|
529 break;
|
|
530 }
|
|
531 } else {
|
|
532 break;
|
|
533 }
|
|
534 }
|
|
535 if (objc - argsused != 2) {
|
|
536 Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
|
|
537 return TCL_ERROR;
|
|
538 }
|
|
539 if ((error = Tcl_GetIntFromObj(interp, objv[argsused++], (int *)&account)) != TCL_OK)
|
|
540 return error;
|
|
541 if (!tcl_validate_account(account, interp))
|
|
542 return TCL_ERROR;
|
|
543 convo = gaim_conversation_new(type, account, Tcl_GetString(objv[argsused]));
|
|
544 Tcl_SetIntObj(result, (int)convo);
|
|
545 break;
|
|
546 case CMD_CONV_WRITE:
|
|
547 if (objc != 6) {
|
|
548 Tcl_WrongNumArgs(interp, 2, objv, "conversation style from what");
|
|
549 return TCL_ERROR;
|
|
550 }
|
|
551 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&convo)) != TCL_OK)
|
|
552 return error;
|
|
553 if ((error = Tcl_GetIndexFromObj(interp, objv[3], styles, "style", 0, (int *)&style)) != TCL_OK)
|
|
554 return error;
|
|
555 if (!tcl_validate_conversation(convo, interp))
|
|
556 return TCL_ERROR;
|
|
557 from = Tcl_GetString(objv[4]);
|
|
558 what = Tcl_GetString(objv[5]);
|
|
559
|
|
560 switch (style) {
|
|
561 case CMD_CONV_WRITE_SEND:
|
|
562 flags = GAIM_MESSAGE_SEND;
|
|
563 break;
|
|
564 case CMD_CONV_WRITE_RECV:
|
|
565 flags = GAIM_MESSAGE_RECV;
|
|
566 break;
|
|
567 case CMD_CONV_WRITE_SYSTEM:
|
|
568 flags = GAIM_MESSAGE_SYSTEM;
|
|
569 break;
|
|
570 }
|
|
571 if (gaim_conversation_get_type(convo) == GAIM_CONV_CHAT)
|
|
572 gaim_chat_write(GAIM_CHAT(convo), from, what, flags, time(NULL));
|
|
573 else
|
|
574 gaim_im_write(GAIM_IM(convo), from, what, -1, flags, time(NULL));
|
|
575 break;
|
|
576 }
|
|
577
|
|
578 return TCL_OK;
|
|
579 }
|
|
580
|
|
581 int tcl_cmd_core(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
582 {
|
|
583 Tcl_Obj *result = Tcl_GetObjResult(interp);
|
|
584 char *cmds[] = { "handle", "quit", NULL };
|
|
585 enum { CMD_CORE_HANDLE, CMD_CORE_QUIT } cmd;
|
|
586 int error;
|
|
587
|
|
588 if (objc < 2) {
|
|
589 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
590 return TCL_ERROR;
|
|
591 }
|
|
592
|
|
593 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
594 return error;
|
|
595
|
|
596 switch (cmd) {
|
|
597 case CMD_CORE_HANDLE:
|
|
598 if (objc != 2) {
|
|
599 Tcl_WrongNumArgs(interp, 2, objv, "");
|
|
600 return TCL_ERROR;
|
|
601 }
|
|
602 Tcl_SetIntObj(result, (int)gaim_get_core());
|
|
603 break;
|
|
604 case CMD_CORE_QUIT:
|
|
605 if (objc != 2) {
|
|
606 Tcl_WrongNumArgs(interp, 2, objv, "");
|
|
607 return TCL_ERROR;
|
|
608 }
|
|
609 gaim_core_quit();
|
|
610 break;
|
|
611 }
|
|
612
|
|
613 return TCL_OK;
|
|
614 }
|
|
615
|
|
616 int tcl_cmd_debug(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
617 {
|
|
618 char *category, *message;
|
|
619 int lev;
|
|
620 char *levels[] = { "-misc", "-info", "-warning", "-error", NULL };
|
|
621 GaimDebugLevel levelind[] = { GAIM_DEBUG_MISC, GAIM_DEBUG_INFO, GAIM_DEBUG_WARNING, GAIM_DEBUG_ERROR };
|
|
622 int error;
|
|
623
|
|
624 if (objc != 4) {
|
|
625 Tcl_WrongNumArgs(interp, 1, objv, "level category message");
|
|
626 return TCL_ERROR;
|
|
627 }
|
|
628
|
|
629 error = Tcl_GetIndexFromObj(interp, objv[1], levels, "debug level", 0, &lev);
|
|
630 if (error != TCL_OK)
|
|
631 return error;
|
|
632
|
|
633 category = Tcl_GetString(objv[2]);
|
|
634 message = Tcl_GetString(objv[3]);
|
|
635
|
|
636 gaim_debug(levelind[lev], category, "%s\n", message);
|
|
637
|
|
638 return TCL_OK;
|
|
639 }
|
|
640
|
|
641 int tcl_cmd_notify(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
642 {
|
|
643 int error, type;
|
|
644 char *opts[] = { "-error", "-warning", "-info", NULL };
|
|
645 GaimNotifyMsgType optind[] = { GAIM_NOTIFY_MSG_ERROR, GAIM_NOTIFY_MSG_WARNING, GAIM_NOTIFY_MSG_INFO };
|
|
646 char *title, *msg1, *msg2;
|
|
647
|
|
648 if (objc < 4 || objc > 5) {
|
|
649 Tcl_WrongNumArgs(interp, 1, objv, "?type? title primary secondary");
|
|
650 return TCL_ERROR;
|
|
651 }
|
|
652
|
|
653 if (objc == 4) {
|
|
654 title = Tcl_GetString(objv[1]);
|
|
655 msg1 = Tcl_GetString(objv[2]);
|
|
656 msg2 = Tcl_GetString(objv[3]);
|
|
657 } else {
|
|
658 error = Tcl_GetIndexFromObj(interp, objv[1], opts, "message type", 0, &type);
|
|
659 if (error != TCL_OK)
|
|
660 return error;
|
|
661 title = Tcl_GetString(objv[2]);
|
|
662 msg1 = Tcl_GetString(objv[3]);
|
|
663 msg2 = Tcl_GetString(objv[4]);
|
|
664 }
|
|
665
|
|
666 gaim_notify_message(_tcl_plugin, optind[type], title, msg1, msg2, NULL, NULL);
|
|
667
|
|
668 return TCL_OK;
|
|
669 }
|
|
670
|
|
671 int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
672 {
|
|
673 Tcl_Obj *result, *list, *elem, **elems;
|
|
674 char *cmds[] = { "get", "set", "type", NULL };
|
|
675 enum { CMD_PREFS_GET, CMD_PREFS_SET, CMD_PREFS_TYPE } cmd;
|
|
676 /* char *types[] = { "none", "boolean", "int", "string", "stringlist", NULL }; */
|
|
677 /* enum { TCL_PREFS_NONE, TCL_PREFS_BOOL, TCL_PREFS_INT, TCL_PREFS_STRING, TCL_PREFS_STRINGLIST } type; */
|
|
678 GaimPrefType preftype;
|
|
679 GList *cur;
|
|
680 int error, intval, nelem, i;
|
|
681
|
|
682 if (objc < 2) {
|
|
683 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
684 return TCL_ERROR;
|
|
685 }
|
|
686
|
|
687 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
688 return error;
|
|
689
|
|
690 result = Tcl_GetObjResult(interp);
|
|
691 switch (cmd) {
|
|
692 case CMD_PREFS_GET:
|
|
693 if (objc != 3) {
|
|
694 Tcl_WrongNumArgs(interp, 1, objv, "path");
|
|
695 return TCL_ERROR;
|
|
696 }
|
|
697 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
|
|
698 switch (preftype) {
|
|
699 case GAIM_PREF_NONE:
|
|
700 Tcl_SetStringObj(result, "pref type none", -1);
|
|
701 return TCL_ERROR;
|
|
702 break;
|
|
703 case GAIM_PREF_BOOLEAN:
|
|
704 Tcl_SetBooleanObj(result, gaim_prefs_get_bool(Tcl_GetString(objv[2])));
|
|
705 break;
|
|
706 case GAIM_PREF_INT:
|
|
707 Tcl_SetIntObj(result, gaim_prefs_get_int(Tcl_GetString(objv[2])));
|
|
708 break;
|
|
709 case GAIM_PREF_STRING:
|
|
710 Tcl_SetStringObj(result, (char *)gaim_prefs_get_string(Tcl_GetString(objv[2])), -1);
|
|
711 break;
|
|
712 case GAIM_PREF_STRING_LIST:
|
|
713 cur = gaim_prefs_get_string_list(Tcl_GetString(objv[2]));
|
|
714 list = Tcl_NewListObj(0, NULL);
|
|
715 while (cur != NULL) {
|
|
716 elem = Tcl_NewStringObj((char *)cur->data, -1);
|
|
717 Tcl_ListObjAppendElement(interp, list, elem);
|
|
718 cur = g_list_next(cur);
|
|
719 }
|
|
720 Tcl_SetObjResult(interp, list);
|
|
721 break;
|
|
722 default:
|
|
723 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
|
|
724 Tcl_SetStringObj(result, "unknown pref type", -1);
|
|
725 return TCL_ERROR;
|
|
726 }
|
|
727 break;
|
|
728 case CMD_PREFS_SET:
|
|
729 if (objc != 4) {
|
|
730 Tcl_WrongNumArgs(interp, 1, objv, "path value");
|
|
731 return TCL_ERROR;
|
|
732 }
|
|
733 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
|
|
734 switch (preftype) {
|
|
735 case GAIM_PREF_NONE:
|
|
736 Tcl_SetStringObj(result, "bad path or pref type none", -1);
|
|
737 return TCL_ERROR;
|
|
738 break;
|
|
739 case GAIM_PREF_BOOLEAN:
|
|
740 if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &intval)) != TCL_OK)
|
|
741 return error;
|
|
742 gaim_prefs_set_bool(Tcl_GetString(objv[2]), intval);
|
|
743 break;
|
|
744 case GAIM_PREF_INT:
|
|
745 if ((error = Tcl_GetIntFromObj(interp, objv[3], &intval)) != TCL_OK)
|
|
746 return error;
|
|
747 gaim_prefs_set_int(Tcl_GetString(objv[2]), intval);
|
|
748 break;
|
|
749 case GAIM_PREF_STRING:
|
|
750 gaim_prefs_set_string(Tcl_GetString(objv[2]), Tcl_GetString(objv[3]));
|
|
751 break;
|
|
752 case GAIM_PREF_STRING_LIST:
|
|
753 if ((error = Tcl_ListObjGetElements(interp, objv[3], &nelem, &elems)) != TCL_OK)
|
|
754 return error;
|
|
755 cur = NULL;
|
|
756 for (i = 0; i < nelem; i++) {
|
|
757 cur = g_list_append(cur, (gpointer)Tcl_GetString(elems[i]));
|
|
758 }
|
|
759 gaim_prefs_set_string_list(Tcl_GetString(objv[2]), cur);
|
|
760 g_list_free(cur);
|
|
761 break;
|
|
762 default:
|
|
763 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
|
|
764 return TCL_ERROR;
|
|
765 }
|
|
766 break;
|
|
767 case CMD_PREFS_TYPE:
|
|
768 if (objc != 3) {
|
|
769 Tcl_WrongNumArgs(interp, 1, objv, "path");
|
|
770 return TCL_ERROR;
|
|
771 }
|
|
772 preftype = gaim_prefs_get_type(Tcl_GetString(objv[2]));
|
|
773 switch (preftype) {
|
|
774 case GAIM_PREF_NONE:
|
|
775 Tcl_SetStringObj(result, "none", -1);
|
|
776 break;
|
|
777 case GAIM_PREF_BOOLEAN:
|
|
778 Tcl_SetStringObj(result, "boolean", -1);
|
|
779 break;
|
|
780 case GAIM_PREF_INT:
|
|
781 Tcl_SetStringObj(result, "int", -1);
|
|
782 break;
|
|
783 case GAIM_PREF_STRING:
|
|
784 Tcl_SetStringObj(result, "string", -1);
|
|
785 break;
|
|
786 case GAIM_PREF_STRING_LIST:
|
|
787 Tcl_SetStringObj(result, "stringlist", -1);
|
|
788 break;
|
|
789 default:
|
|
790 gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
|
|
791 Tcl_SetStringObj(result, "unknown", -1);
|
|
792 }
|
|
793 break;
|
|
794 }
|
|
795
|
|
796 return TCL_OK;
|
|
797 }
|
|
798
|
|
799 int tcl_cmd_send_im(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
800 {
|
|
801 GaimConnection *gc;
|
|
802 char *who, *text;
|
|
803 int error;
|
|
804 Tcl_Obj *result;
|
|
805
|
|
806 if (objc != 4) {
|
|
807 Tcl_WrongNumArgs(interp, 1, objv, "gc who text");
|
|
808 return TCL_ERROR;
|
|
809 }
|
|
810
|
|
811 if ((error = Tcl_GetIntFromObj(interp, objv[1], (int *)&gc)) != TCL_OK)
|
|
812 return error;
|
|
813 if (!tcl_validate_gc(gc)) {
|
|
814 result = Tcl_GetObjResult(interp);
|
|
815 Tcl_SetStringObj(result, "invalid gc", -1);
|
|
816 return TCL_ERROR;
|
|
817 }
|
|
818
|
|
819 who = Tcl_GetString(objv[2]);
|
|
820 text = Tcl_GetString(objv[3]);
|
|
821
|
|
822 serv_send_im(gc, who, text, -1, 0);
|
|
823
|
|
824 return TCL_OK;
|
|
825 }
|
|
826
|
|
827 int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
828 {
|
|
829 char *cmds[] = { "connect", "disconnect", NULL };
|
|
830 enum { CMD_SIGNAL_CONNECT, CMD_SIGNAL_DISCONNECT } cmd;
|
|
831 struct tcl_signal_handler *handler;
|
|
832 Tcl_Obj **elems, *result = Tcl_GetObjResult(interp);
|
|
833 void *instance;
|
|
834 int error, nelems, i;
|
|
835
|
|
836 if (objc < 2) {
|
|
837 Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
|
|
838 return TCL_ERROR;
|
|
839 }
|
|
840
|
|
841 if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
|
|
842 return error;
|
|
843
|
|
844 switch (cmd) {
|
|
845 case CMD_SIGNAL_CONNECT:
|
|
846 if (objc != 6) {
|
|
847 Tcl_WrongNumArgs(interp, 2, objv, "instance signal args proc");
|
|
848 return TCL_ERROR;
|
|
849 }
|
|
850 if ((error = Tcl_ListObjGetElements(interp, objv[4], &nelems, &elems)) != TCL_OK)
|
|
851 return error;
|
|
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 = g_strdup(Tcl_GetString(objv[3]));
|
|
858 if (nelems) {
|
|
859 handler->argnames = g_new0(char *, nelems);
|
|
860 for (i = 0; i < nelems; i++) {
|
|
861 handler->argnames[i] = g_strdup(Tcl_GetString(elems[i]));
|
|
862 }
|
|
863 }
|
|
864 handler->nnames = nelems;
|
|
865 handler->proc = Tcl_NewStringObj("namespace eval ::gaim::_callback { ", -1);
|
|
866 Tcl_AppendStringsToObj(handler->proc, Tcl_GetString(objv[5]), " }", NULL);
|
|
867 Tcl_IncrRefCount(handler->proc);
|
|
868 handler->interp = interp;
|
|
869 if (!tcl_signal_connect(handler)) {
|
|
870 tcl_signal_handler_free(handler);
|
|
871 Tcl_SetIntObj(result, 1);
|
|
872 } else {
|
|
873 Tcl_SetIntObj(result, 0);
|
|
874 }
|
|
875 break;
|
|
876 case CMD_SIGNAL_DISCONNECT:
|
|
877 if (objc != 4) {
|
|
878 Tcl_WrongNumArgs(interp, 2, objv, "signal");
|
|
879 return TCL_ERROR;
|
|
880 }
|
|
881 if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&instance)) != TCL_OK)
|
|
882 return error;
|
|
883 tcl_signal_disconnect(instance, Tcl_GetString(objv[3]), interp);
|
|
884 break;
|
|
885 }
|
|
886
|
|
887 return TCL_OK;
|
|
888 }
|
|
889
|
|
890 static gboolean unload_self(gpointer data)
|
|
891 {
|
|
892 GaimPlugin *plugin = data;
|
|
893 gaim_plugin_unload(plugin);
|
|
894 return FALSE;
|
|
895 }
|
|
896
|
|
897 int tcl_cmd_unload(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
|
898 {
|
|
899 GaimPlugin *plugin;
|
|
900 if (objc != 1) {
|
|
901 Tcl_WrongNumArgs(interp, 1, objv, "");
|
|
902 return TCL_ERROR;
|
|
903 }
|
|
904
|
|
905 if ((plugin = tcl_interp_get_plugin(interp)) == NULL) {
|
|
906 /* This isn't exactly OK, but heh. What do you do? */
|
|
907 return TCL_OK;
|
|
908 }
|
|
909 /* We can't unload immediately, but we can unload at the first
|
|
910 * known safe opportunity. */
|
|
911 g_idle_add(unload_self, (gpointer)plugin);
|
|
912
|
|
913 return TCL_OK;
|
|
914 }
|