gee
oldstatus
2005-09-19, Nathan Walp
* @file tcl_cmds.c Commands for the Gaim Tcl plugin bindings * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu> * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "conversation.h" static gboolean tcl_validate_account(GaimAccount *account, Tcl_Interp *interp); static gboolean tcl_validate_gc(GaimConnection *gc); static gboolean tcl_validate_account(GaimAccount *account, Tcl_Interp *interp) for (cur = gaim_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) { if (account == cur->data) Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1); static gboolean tcl_validate_conversation(GaimConversation *convo, Tcl_Interp *interp) for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) { Tcl_SetStringObj(Tcl_GetObjResult(interp), "invalid account", -1); static gboolean tcl_validate_gc(GaimConnection *gc) for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) { int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem; const char *cmds[] = { "alias", "connect", "connection", "disconnect", "find", "handle", "isconnected", "list", "protocol", "username", NULL }; enum { CMD_ACCOUNT_ALIAS, CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION, CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_FIND, CMD_ACCOUNT_HANDLE, CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST, CMD_ACCOUNT_PROTOCOL, CMD_ACCOUNT_USERNAME } cmd; const char *listopts[] = { "-all", "-online", NULL }; enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) alias = gaim_account_get_alias(account); Tcl_SetStringObj(result, alias ? (char *)alias : "", -1); case CMD_ACCOUNT_CONNECT: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) if (gaim_account_is_connected(account)) Tcl_SetIntObj(result, (int)gaim_account_get_connection(account)); Tcl_SetIntObj(result, (int)gaim_account_connect(account)); case CMD_ACCOUNT_CONNECTION: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) Tcl_SetIntObj(result, (int)gaim_account_get_connection(account)); case CMD_ACCOUNT_DISCONNECT: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) gaim_account_disconnect(account); Tcl_WrongNumArgs(interp, 2, objv, "username protocol"); Tcl_SetIntObj(result, (int)gaim_accounts_find(Tcl_GetString(objv[2]), Tcl_GetString(objv[3]))); Tcl_WrongNumArgs(interp, 2, objv, ""); Tcl_SetIntObj(result, (int)gaim_accounts_get_handle()); case CMD_ACCOUNT_ISCONNECTED: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) Tcl_SetBooleanObj(result, gaim_account_is_connected(account)); listopt = CMD_ACCOUNTLIST_ALL; Tcl_WrongNumArgs(interp, 2, objv, "?option?"); if ((error = Tcl_GetIndexFromObj(interp, objv[2], listopts, "option", 0, (int *)&listopt)) != TCL_OK) list = Tcl_NewListObj(0, NULL); for (cur = gaim_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) { if (listopt == CMD_ACCOUNTLIST_ONLINE && !gaim_account_is_connected(account)) elem = Tcl_NewIntObj((int)account); Tcl_ListObjAppendElement(interp, list, elem); Tcl_SetObjResult(interp, list); case CMD_ACCOUNT_PROTOCOL: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) Tcl_SetStringObj(result, (char *)gaim_account_get_protocol_id(account), -1); case CMD_ACCOUNT_USERNAME: Tcl_WrongNumArgs(interp, 2, objv, "account"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account); if (error || !tcl_validate_account(account, interp)) Tcl_SetStringObj(result, (char *)gaim_account_get_username(account), -1); static GaimBlistNode *tcl_list_to_buddy(Tcl_Interp *interp, int count, Tcl_Obj **elems) GaimBlistNode *node = NULL; Tcl_SetStringObj(Tcl_GetObjResult(interp), "list too short", -1); type = Tcl_GetString(elems[0]); name = Tcl_GetString(elems[1]); if (Tcl_GetIntFromObj(interp, elems[2], (int *)&account) != TCL_OK) if (!tcl_validate_account(account, interp)) if (!strcmp(type, "buddy")) { node = (GaimBlistNode *)gaim_find_buddy(account, name); } else if (!strcmp(type, "group")) { node = (GaimBlistNode *)gaim_blist_find_chat(account, name); int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *list, *tclgroup, *tclgrouplist, *tclcontact, *tclcontactlist, *tclbud, **elems, *result; const char *cmds[] = { "alias", "handle", "info", "list", NULL }; enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd; GaimBlistNode *node, *gnode, *bnode; int error, all = 0, count; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) result = Tcl_GetObjResult(interp); Tcl_WrongNumArgs(interp, 2, objv, "buddy"); if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK) if ((node = tcl_list_to_buddy(interp, count, elems)) == NULL) if (node->type == GAIM_BLIST_CHAT_NODE) Tcl_SetStringObj(result, ((GaimChat *)node)->alias, -1); else if (node->type == GAIM_BLIST_BUDDY_NODE) Tcl_SetStringObj(result, (char *)gaim_buddy_get_alias((GaimBuddy *)node), -1); Tcl_WrongNumArgs(interp, 2, objv, ""); Tcl_SetIntObj(result, (int)gaim_blist_get_handle()); if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "( buddy | account username )"); if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK) Tcl_SetStringObj(result, "buddy too short", -1); if (strcmp("buddy", Tcl_GetString(elems[0]))) { Tcl_SetStringObj(result, "invalid buddy", -1); if ((error = Tcl_GetIntFromObj(interp, elems[2], (int *)&account)) != TCL_OK) if (!tcl_validate_account(account, interp)) serv_get_info(gaim_account_get_connection(account), Tcl_GetString(elems[1])); if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account)) != TCL_OK) if (!tcl_validate_account(account, interp)) serv_get_info(gaim_account_get_connection(account), Tcl_GetString(objv[3])); if (!strcmp("-all", Tcl_GetString(objv[2]))) { Tcl_SetStringObj(result, "", -1); Tcl_AppendStringsToObj(result, "unknown option: ", Tcl_GetString(objv[2]), NULL); list = Tcl_NewListObj(0, NULL); blist = gaim_get_blist(); for (gnode = blist->root; gnode != NULL; gnode = gnode->next) { tclgroup = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj("group", -1)); Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj(((GaimGroup *)gnode)->name, -1)); tclgrouplist = Tcl_NewListObj(0, NULL); for (node = gnode->child; node != NULL; node = node->next) { case GAIM_BLIST_CONTACT_NODE: tclcontact = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(tclcontact); Tcl_ListObjAppendElement(interp, tclcontact, Tcl_NewStringObj("contact", -1)); tclcontactlist = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(tclcontactlist); for (bnode = node->child; bnode != NULL; bnode = bnode ->next) { if (bnode->type != GAIM_BLIST_BUDDY_NODE) bud = (GaimBuddy *)bnode; if (!all && !gaim_account_is_connected(bud->account)) tclbud = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("buddy", -1)); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(bud->name, -1)); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)bud->account)); Tcl_ListObjAppendElement(interp, tclcontactlist, tclbud); Tcl_ListObjAppendElement(interp, tclcontact, tclcontactlist); Tcl_ListObjAppendElement(interp, tclgrouplist, tclcontact); Tcl_DecrRefCount(tclcontact); Tcl_DecrRefCount(tclcontactlist); case GAIM_BLIST_CHAT_NODE: cnode = (GaimChat *)node; if (!all && !gaim_account_is_connected(cnode->account)) tclbud = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("chat", -1)); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(cnode->alias, -1)); Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewIntObj((int)cnode->account)); Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud); gaim_debug(GAIM_DEBUG_WARNING, "tcl", "Unexpected buddy type %d", node->type); Tcl_ListObjAppendElement(interp, tclgroup, tclgrouplist); Tcl_ListObjAppendElement(interp, list, tclgroup); Tcl_SetObjResult(interp, list); int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem; const char *cmds[] = { "account", "displayname", "handle", "list", NULL }; enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) Tcl_WrongNumArgs(interp, 2, objv, "gc"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&gc); if (error || !tcl_validate_gc(gc)) { Tcl_SetStringObj(result, "invalid gc", -1); Tcl_SetIntObj(result, (int)gaim_connection_get_account(gc)); case CMD_CONN_DISPLAYNAME: Tcl_WrongNumArgs(interp, 2, objv, "gc"); error = Tcl_GetIntFromObj(interp, objv[2], (int *)&gc); if (error || !tcl_validate_gc(gc)) { Tcl_SetStringObj(result, "invalid gc", -1); Tcl_SetStringObj(result, (char *)gaim_connection_get_display_name(gc), -1); Tcl_WrongNumArgs(interp, 2, objv, ""); Tcl_SetIntObj(result, (int)gaim_connections_get_handle()); Tcl_WrongNumArgs(interp, 2, objv, ""); list = Tcl_NewListObj(0, NULL); for (cur = gaim_connections_get_all(); cur != NULL; cur = g_list_next(cur)) { elem = Tcl_NewIntObj((int)cur->data); Tcl_ListObjAppendElement(interp, list, elem); Tcl_SetObjResult(interp, list); int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *list, *elem, *result = Tcl_GetObjResult(interp); const char *cmds[] = { "find", "handle", "list", "new", "write", NULL }; enum { CMD_CONV_FIND, CMD_CONV_HANDLE, CMD_CONV_LIST, CMD_CONV_NEW, CMD_CONV_WRITE } cmd; const char *styles[] = { "send", "recv", "system", NULL }; enum { CMD_CONV_WRITE_SEND, CMD_CONV_WRITE_RECV, CMD_CONV_WRITE_SYSTEM } style; const char *findopts[] = { "-account", NULL }; enum { CMD_CONV_FIND_ACCOUNT } findopt; const char *newopts[] = { "-chat", "-im" }; enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt; GaimConversationType type; int error, argsused, flags = 0; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) Tcl_WrongNumArgs(interp, 2, objv, "?options? name"); while (argsused < objc) { opt = Tcl_GetString(objv[argsused]); if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], findopts, "option", 0, (int *)&findopt)) != TCL_OK) case CMD_CONV_FIND_ACCOUNT: if (argsused == objc - 1) { Tcl_SetStringObj(result, "-account requires an argument", -1); if ((error = Tcl_GetIntFromObj(interp, objv[argsused], (int *)&account)) != TCL_OK) if (!tcl_validate_account(account, interp)) if (objc - argsused != 1) { Tcl_WrongNumArgs(interp, 2, objv, "?options? name"); convo = gaim_find_conversation_with_account(Tcl_GetString(objv[argsused]), account); convo = gaim_find_conversation(Tcl_GetString(objv[argsused])); Tcl_SetIntObj(result, (int)convo); Tcl_WrongNumArgs(interp, 2, objv, ""); Tcl_SetIntObj(result, (int)gaim_conversations_get_handle()); list = Tcl_NewListObj(0, NULL); for (cur = gaim_get_conversations(); cur != NULL; cur = g_list_next(cur)) { elem = Tcl_NewIntObj((int)cur->data); Tcl_ListObjAppendElement(interp, list, elem); Tcl_SetObjResult(interp, list); Tcl_WrongNumArgs(interp, 2, objv, "?options? account name"); while (argsused < objc) { opt = Tcl_GetString(objv[argsused]); if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], newopts, "option", 0, (int *)&newopt)) != TCL_OK) if (objc - argsused != 2) { Tcl_WrongNumArgs(interp, 2, objv, "?options? account name"); if ((error = Tcl_GetIntFromObj(interp, objv[argsused++], (int *)&account)) != TCL_OK) if (!tcl_validate_account(account, interp)) convo = gaim_conversation_new(type, account, Tcl_GetString(objv[argsused])); Tcl_SetIntObj(result, (int)convo); Tcl_WrongNumArgs(interp, 2, objv, "conversation style from what"); if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&convo)) != TCL_OK) if ((error = Tcl_GetIndexFromObj(interp, objv[3], styles, "style", 0, (int *)&style)) != TCL_OK) if (!tcl_validate_conversation(convo, interp)) from = Tcl_GetString(objv[4]); what = Tcl_GetString(objv[5]); case CMD_CONV_WRITE_SEND: flags = GAIM_MESSAGE_SEND; case CMD_CONV_WRITE_RECV: flags = GAIM_MESSAGE_RECV; case CMD_CONV_WRITE_SYSTEM: flags = GAIM_MESSAGE_SYSTEM; if (gaim_conversation_get_type(convo) == GAIM_CONV_CHAT) gaim_conv_chat_write(GAIM_CONV_CHAT(convo), from, what, flags, time(NULL)); gaim_conv_im_write(GAIM_CONV_IM(convo), from, what, flags, time(NULL)); int tcl_cmd_core(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *result = Tcl_GetObjResult(interp); const char *cmds[] = { "handle", "quit", NULL }; enum { CMD_CORE_HANDLE, CMD_CORE_QUIT } cmd; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) Tcl_WrongNumArgs(interp, 2, objv, ""); Tcl_SetIntObj(result, (int)gaim_get_core()); Tcl_WrongNumArgs(interp, 2, objv, ""); int tcl_cmd_debug(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) char *category, *message; const char *levels[] = { "-misc", "-info", "-warning", "-error", NULL }; GaimDebugLevel levelind[] = { GAIM_DEBUG_MISC, GAIM_DEBUG_INFO, GAIM_DEBUG_WARNING, GAIM_DEBUG_ERROR }; Tcl_WrongNumArgs(interp, 1, objv, "level category message"); error = Tcl_GetIndexFromObj(interp, objv[1], levels, "debug level", 0, &lev); category = Tcl_GetString(objv[2]); message = Tcl_GetString(objv[3]); gaim_debug(levelind[lev], category, "%s\n", message); int tcl_cmd_notify(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) const char *opts[] = { "-error", "-warning", "-info", NULL }; GaimNotifyMsgType optind[] = { GAIM_NOTIFY_MSG_ERROR, GAIM_NOTIFY_MSG_WARNING, GAIM_NOTIFY_MSG_INFO }; char *title, *msg1, *msg2; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "?type? title primary secondary"); title = Tcl_GetString(objv[1]); msg1 = Tcl_GetString(objv[2]); msg2 = Tcl_GetString(objv[3]); error = Tcl_GetIndexFromObj(interp, objv[1], opts, "message type", 0, &type); title = Tcl_GetString(objv[2]); msg1 = Tcl_GetString(objv[3]); msg2 = Tcl_GetString(objv[4]); gaim_notify_message(_tcl_plugin, optind[type], title, msg1, msg2, NULL, NULL); int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_Obj *result, *list, *elem, **elems; const char *cmds[] = { "get", "set", "type", NULL }; enum { CMD_PREFS_GET, CMD_PREFS_SET, CMD_PREFS_TYPE } cmd; /* char *types[] = { "none", "boolean", "int", "string", "stringlist", NULL }; */ /* enum { TCL_PREFS_NONE, TCL_PREFS_BOOL, TCL_PREFS_INT, TCL_PREFS_STRING, TCL_PREFS_STRINGLIST } type; */ int error, intval, nelem, i; Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) result = Tcl_GetObjResult(interp); Tcl_WrongNumArgs(interp, 1, objv, "path"); preftype = gaim_prefs_get_type(Tcl_GetString(objv[2])); Tcl_SetStringObj(result, "pref type none", -1); Tcl_SetBooleanObj(result, gaim_prefs_get_bool(Tcl_GetString(objv[2]))); Tcl_SetIntObj(result, gaim_prefs_get_int(Tcl_GetString(objv[2]))); Tcl_SetStringObj(result, (char *)gaim_prefs_get_string(Tcl_GetString(objv[2])), -1); case GAIM_PREF_STRING_LIST: cur = gaim_prefs_get_string_list(Tcl_GetString(objv[2])); list = Tcl_NewListObj(0, NULL); elem = Tcl_NewStringObj((char *)cur->data, -1); Tcl_ListObjAppendElement(interp, list, elem); Tcl_SetObjResult(interp, list); gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype); Tcl_SetStringObj(result, "unknown pref type", -1); Tcl_WrongNumArgs(interp, 1, objv, "path value"); preftype = gaim_prefs_get_type(Tcl_GetString(objv[2])); Tcl_SetStringObj(result, "bad path or pref type none", -1); if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &intval)) != TCL_OK) gaim_prefs_set_bool(Tcl_GetString(objv[2]), intval); if ((error = Tcl_GetIntFromObj(interp, objv[3], &intval)) != TCL_OK) gaim_prefs_set_int(Tcl_GetString(objv[2]), intval); gaim_prefs_set_string(Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); case GAIM_PREF_STRING_LIST: if ((error = Tcl_ListObjGetElements(interp, objv[3], &nelem, &elems)) != TCL_OK) for (i = 0; i < nelem; i++) { cur = g_list_append(cur, (gpointer)Tcl_GetString(elems[i])); gaim_prefs_set_string_list(Tcl_GetString(objv[2]), cur); gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype); Tcl_WrongNumArgs(interp, 1, objv, "path"); preftype = gaim_prefs_get_type(Tcl_GetString(objv[2])); Tcl_SetStringObj(result, "none", -1); Tcl_SetStringObj(result, "boolean", -1); Tcl_SetStringObj(result, "int", -1); Tcl_SetStringObj(result, "string", -1); case GAIM_PREF_STRING_LIST: Tcl_SetStringObj(result, "stringlist", -1); gaim_debug(GAIM_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype); Tcl_SetStringObj(result, "unknown", -1); int tcl_cmd_send_im(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_WrongNumArgs(interp, 1, objv, "gc who text"); if ((error = Tcl_GetIntFromObj(interp, objv[1], (int *)&gc)) != TCL_OK) if (!tcl_validate_gc(gc)) { result = Tcl_GetObjResult(interp); Tcl_SetStringObj(result, "invalid gc", -1); who = Tcl_GetString(objv[2]); text = Tcl_GetString(objv[3]); serv_send_im(gc, who, text, 0); int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) const char *cmds[] = { "connect", "disconnect", NULL }; enum { CMD_SIGNAL_CONNECT, CMD_SIGNAL_DISCONNECT } cmd; struct tcl_signal_handler *handler; Tcl_Obj **elems, *result = Tcl_GetObjResult(interp); Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK) Tcl_WrongNumArgs(interp, 2, objv, "instance signal args proc"); if ((error = Tcl_ListObjGetElements(interp, objv[4], &nelems, &elems)) != TCL_OK) handler = g_new0(struct tcl_signal_handler, 1); if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&handler->instance)) != TCL_OK) { handler->signal = g_strdup(Tcl_GetString(objv[3])); handler->argnames = g_new0(char *, nelems); for (i = 0; i < nelems; i++) { handler->argnames[i] = g_strdup(Tcl_GetString(elems[i])); handler->nnames = nelems; handler->proc = Tcl_NewStringObj("namespace eval ::gaim::_callback { ", -1); Tcl_AppendStringsToObj(handler->proc, Tcl_GetString(objv[5]), " }", NULL); Tcl_IncrRefCount(handler->proc); handler->interp = interp; if (!tcl_signal_connect(handler)) { tcl_signal_handler_free(handler); Tcl_SetIntObj(result, 1); Tcl_SetIntObj(result, 0); case CMD_SIGNAL_DISCONNECT: Tcl_WrongNumArgs(interp, 2, objv, "signal"); if ((error = Tcl_GetIntFromObj(interp, objv[2], (int *)&instance)) != TCL_OK) tcl_signal_disconnect(instance, Tcl_GetString(objv[3]), interp); static gboolean unload_self(gpointer data) GaimPlugin *plugin = data; gaim_plugin_unload(plugin); int tcl_cmd_unload(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) Tcl_WrongNumArgs(interp, 1, objv, ""); if ((plugin = tcl_interp_get_plugin(interp)) == NULL) { /* This isn't exactly OK, but heh. What do you do? */ /* We can't unload immediately, but we can unload at the first * known safe opportunity. */ g_idle_add(unload_self, (gpointer)plugin);