Mercurial > pidgin
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 } |