Sun, 28 Jul 2013 23:36:59 +0530
Replaced purple_find_prpl() with purple_find_protocol_info().
* Changed its return type from PurplePlugin * to PurplePluginProtocolInfo *
* Added id to PurplePluginProtocolInfo
| 13847 | 1 | /** |
| 15884 | 2 | * @file tcl_cmd.c Purple Tcl cmd API |
| 13847 | 3 | * |
| 15884 | 4 | * purple |
| 13847 | 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 | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
15884
diff
changeset
|
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 13847 | 21 | */ |
| 22 | #include <tcl.h> | |
| 23 | ||
| 15884 | 24 | #include "tcl_purple.h" |
| 13847 | 25 | |
| 26 | #include "internal.h" | |
| 27 | #include "cmds.h" | |
| 28 | #include "debug.h" | |
| 29 | ||
| 30 | static GList *tcl_cmd_callbacks; | |
| 31 | ||
| 15884 | 32 | static PurpleCmdRet tcl_cmd_callback(PurpleConversation *conv, const gchar *cmd, |
| 13847 | 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) { | |
| 15884 | 59 | purple_cmd_unregister(handler->id); |
| 13847 | 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 | ||
| 15884 | 67 | PurpleCmdId tcl_cmd_register(struct tcl_cmd_handler *handler) |
| 13847 | 68 | { |
| 69 | int id; | |
| 70 | GString *proc; | |
| 71 | ||
| 15884 | 72 | if ((id = purple_cmd_register(Tcl_GetString(handler->cmd), |
| 13847 | 73 | handler->args, handler->priority, |
| 74 | handler->flags, handler->prpl_id, | |
| 15884 | 75 | PURPLE_CMD_FUNC(tcl_cmd_callback), |
| 13847 | 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 | ||
| 15884 | 97 | void tcl_cmd_unregister(PurpleCmdId id, Tcl_Interp *interp) |
| 13847 | 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) { | |
| 15884 | 107 | purple_cmd_unregister(id); |
| 13847 | 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 | ||
| 15884 | 124 | static PurpleCmdRet tcl_cmd_callback(PurpleConversation *conv, const gchar *cmd, |
| 13847 | 125 | gchar **args, gchar **errors, |
| 126 | struct tcl_cmd_handler *handler) | |
| 127 | { | |
|
30626
bec413ce77c7
Fix some "Dead nested assignment"s and then kill off some useless
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
24683
diff
changeset
|
128 | int retval, i; |
| 13847 | 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 */ | |
| 15884 | 140 | arg = purple_tcl_ref_new(PurpleTclRefConversation, conv); |
| 13847 | 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 | ||
|
30626
bec413ce77c7
Fix some "Dead nested assignment"s and then kill off some useless
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
24683
diff
changeset
|
156 | if (Tcl_EvalObjEx(handler->interp, command, TCL_EVAL_GLOBAL) != TCL_OK) { |
| 13847 | 157 | gchar *errorstr; |
| 158 | ||
| 159 | errorstr = g_strdup_printf("error evaluating callback: %s\n", | |
| 160 | Tcl_GetString(Tcl_GetObjResult(handler->interp))); | |
|
24683
3481a3320313
Backport the 'purple_debug_*(msg)' -> 'purple_debug_*("%s", msg);' fixes.
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
161 | purple_debug(PURPLE_DEBUG_ERROR, "tcl", "%s", errorstr); |
| 13847 | 162 | *errors = errorstr; |
| 15884 | 163 | retval = PURPLE_CMD_RET_FAILED; |
| 13847 | 164 | } else { |
| 165 | result = Tcl_GetObjResult(handler->interp); | |
|
30626
bec413ce77c7
Fix some "Dead nested assignment"s and then kill off some useless
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
24683
diff
changeset
|
166 | if (Tcl_GetIntFromObj(handler->interp, result, |
|
bec413ce77c7
Fix some "Dead nested assignment"s and then kill off some useless
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
24683
diff
changeset
|
167 | &retval) != TCL_OK) { |
| 13847 | 168 | gchar *errorstr; |
| 169 | ||
| 170 | errorstr = g_strdup_printf("Error retreiving procedure result: %s\n", | |
| 171 | Tcl_GetString(Tcl_GetObjResult(handler->interp))); | |
|
24683
3481a3320313
Backport the 'purple_debug_*(msg)' -> 'purple_debug_*("%s", msg);' fixes.
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
172 | purple_debug(PURPLE_DEBUG_ERROR, "tcl", "%s", errorstr); |
| 13847 | 173 | *errors = errorstr; |
| 15884 | 174 | retval = PURPLE_CMD_RET_FAILED; |
| 13847 | 175 | } |
| 176 | } | |
| 177 | ||
| 178 | return retval; | |
| 179 | } | |
| 180 | ||
| 181 | static Tcl_Obj *new_cmd_cb_namespace() | |
| 182 | { | |
| 183 | char name[32]; | |
| 184 | static int cbnum; | |
| 185 | ||
| 15884 | 186 | g_snprintf(name, sizeof(name), "::purple::_cmd_callback::cb_%d", |
| 13850 | 187 | cbnum++); |
| 13847 | 188 | return Tcl_NewStringObj(name, -1); |
| 189 | } |