comparison libpurple/plugins/tcl/tcl_cmd.c @ 15373:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 32c366eeeb99
comparison
equal deleted inserted replaced
15372:f79e0f4df793 15373:5fe8042783c1
1 /**
2 * @file tcl_cmd.c Gaim Tcl cmd API
3 *
4 * gaim
5 *
6 * Copyright (C) 2006 Etan Reisner <deryni@gmail.com>
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 #include <tcl.h>
23
24 #include "tcl_gaim.h"
25
26 #include "internal.h"
27 #include "cmds.h"
28 #include "debug.h"
29
30 static GList *tcl_cmd_callbacks;
31
32 static GaimCmdRet tcl_cmd_callback(GaimConversation *conv, const gchar *cmd,
33 gchar **args, gchar **errors,
34 struct tcl_cmd_handler *handler);
35 static Tcl_Obj *new_cmd_cb_namespace(void);
36
37 void tcl_cmd_init()
38 {
39 tcl_cmd_callbacks = NULL;
40 }
41
42 void tcl_cmd_handler_free(struct tcl_cmd_handler *handler)
43 {
44 if (handler == NULL)
45 return;
46
47 Tcl_DecrRefCount(handler->namespace);
48 g_free(handler);
49 }
50
51 void tcl_cmd_cleanup(Tcl_Interp *interp)
52 {
53 GList *cur;
54 struct tcl_cmd_handler *handler;
55
56 for (cur = tcl_cmd_callbacks; cur != NULL; cur = g_list_next(cur)) {
57 handler = cur->data;
58 if (handler->interp == interp) {
59 gaim_cmd_unregister(handler->id);
60 tcl_cmd_handler_free(handler);
61 cur->data = NULL;
62 }
63 }
64 tcl_cmd_callbacks = g_list_remove_all(tcl_cmd_callbacks, NULL);
65 }
66
67 GaimCmdId tcl_cmd_register(struct tcl_cmd_handler *handler)
68 {
69 int id;
70 GString *proc;
71
72 if ((id = gaim_cmd_register(Tcl_GetString(handler->cmd),
73 handler->args, handler->priority,
74 handler->flags, handler->prpl_id,
75 GAIM_CMD_FUNC(tcl_cmd_callback),
76 handler->helpstr, (void *)handler)) == 0)
77 return 0;
78
79 handler->namespace = new_cmd_cb_namespace ();
80 Tcl_IncrRefCount(handler->namespace);
81 proc = g_string_new("");
82 g_string_append_printf(proc, "namespace eval %s { proc cb { conv cmd arglist } { %s } }",
83 Tcl_GetString(handler->namespace),
84 Tcl_GetString(handler->proc));
85 if (Tcl_Eval(handler->interp, proc->str) != TCL_OK) {
86 Tcl_DecrRefCount(handler->namespace);
87 g_string_free(proc, TRUE);
88 return 0;
89 }
90 g_string_free(proc, TRUE);
91
92 tcl_cmd_callbacks = g_list_append(tcl_cmd_callbacks, (gpointer)handler);
93
94 return id;
95 }
96
97 void tcl_cmd_unregister(GaimCmdId id, Tcl_Interp *interp)
98 {
99 GList *cur;
100 GString *cmd;
101 gboolean found = FALSE;
102 struct tcl_cmd_handler *handler;
103
104 for (cur = tcl_cmd_callbacks; cur != NULL; cur = g_list_next(cur)) {
105 handler = cur->data;
106 if (handler->interp == interp && handler->id == id) {
107 gaim_cmd_unregister(id);
108 cmd = g_string_sized_new(64);
109 g_string_printf(cmd, "namespace delete %s",
110 Tcl_GetString(handler->namespace));
111 Tcl_EvalEx(interp, cmd->str, -1, TCL_EVAL_GLOBAL);
112 tcl_cmd_handler_free(handler);
113 g_string_free(cmd, TRUE);
114 cur->data = NULL;
115 found = TRUE;
116 break;
117 }
118 }
119
120 if (found)
121 tcl_cmd_callbacks = g_list_remove_all(tcl_cmd_callbacks, NULL);
122 }
123
124 static GaimCmdRet tcl_cmd_callback(GaimConversation *conv, const gchar *cmd,
125 gchar **args, gchar **errors,
126 struct tcl_cmd_handler *handler)
127 {
128 int retval, error, i;
129 Tcl_Obj *command, *arg, *tclargs, *result;
130
131 command = Tcl_NewListObj(0, NULL);
132 Tcl_IncrRefCount(command);
133
134 /* The callback */
135 arg = Tcl_DuplicateObj(handler->namespace);
136 Tcl_AppendStringsToObj(arg, "::cb", NULL);
137 Tcl_ListObjAppendElement(handler->interp, command, arg);
138
139 /* The conversation */
140 arg = gaim_tcl_ref_new(GaimTclRefConversation, conv);
141 Tcl_ListObjAppendElement(handler->interp, command, arg);
142
143 /* The command */
144 arg = Tcl_NewStringObj(cmd, -1);
145 Tcl_ListObjAppendElement(handler->interp, command, arg);
146
147 /* The args list */
148 tclargs = Tcl_NewListObj(0, NULL);
149 for (i = 0; i < handler->nargs; i++) {
150 arg = Tcl_NewStringObj(args[i], -1);
151
152 Tcl_ListObjAppendElement(handler->interp, tclargs, arg);
153 }
154 Tcl_ListObjAppendElement(handler->interp, command, tclargs);
155
156 if ((error = Tcl_EvalObjEx(handler->interp, command,
157 TCL_EVAL_GLOBAL)) != TCL_OK) {
158 gchar *errorstr;
159
160 errorstr = g_strdup_printf("error evaluating callback: %s\n",
161 Tcl_GetString(Tcl_GetObjResult(handler->interp)));
162 gaim_debug(GAIM_DEBUG_ERROR, "tcl", errorstr);
163 *errors = errorstr;
164 retval = GAIM_CMD_RET_FAILED;
165 } else {
166 result = Tcl_GetObjResult(handler->interp);
167 if ((error = Tcl_GetIntFromObj(handler->interp, result,
168 &retval)) != TCL_OK) {
169 gchar *errorstr;
170
171 errorstr = g_strdup_printf("Error retreiving procedure result: %s\n",
172 Tcl_GetString(Tcl_GetObjResult(handler->interp)));
173 gaim_debug(GAIM_DEBUG_ERROR, "tcl", errorstr);
174 *errors = errorstr;
175 retval = GAIM_CMD_RET_FAILED;
176 }
177 }
178
179 return retval;
180 }
181
182 static Tcl_Obj *new_cmd_cb_namespace()
183 {
184 char name[32];
185 static int cbnum;
186
187 g_snprintf(name, sizeof(name), "::gaim::_cmd_callback::cb_%d",
188 cbnum++);
189 return Tcl_NewStringObj(name, -1);
190 }