libpurple/cmds.c

changeset 40884
ca31392953ed
parent 40564
2c5b4dc2e86a
child 41685
ca22b00972d4
equal deleted inserted replaced
40883:8f377fd478c0 40884:ca31392953ed
39 } PurpleCmd; 39 } PurpleCmd;
40 40
41 41
42 static gint cmds_compare_func(const PurpleCmd *a, const PurpleCmd *b) 42 static gint cmds_compare_func(const PurpleCmd *a, const PurpleCmd *b)
43 { 43 {
44 if (a->priority > b->priority) 44 return b->priority - a->priority;
45 return -1;
46 else if (a->priority < b->priority)
47 return 1;
48 else return 0;
49 } 45 }
50 46
51 PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, 47 PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args,
52 PurpleCmdPriority p, PurpleCmdFlag f, 48 PurpleCmdPriority p, PurpleCmdFlag f,
53 const gchar *protocol_id, PurpleCmdFunc func, 49 const gchar *protocol_id, PurpleCmdFunc func,
92 g_free(c->protocol_id); 88 g_free(c->protocol_id);
93 g_free(c->help); 89 g_free(c->help);
94 g_free(c); 90 g_free(c);
95 } 91 }
96 92
93 static gint
94 purple_cmd_cmp_id(gconstpointer cmd, gconstpointer id)
95 {
96 return ((PurpleCmd *)cmd)->id - GPOINTER_TO_UINT(id);
97 }
98
97 void purple_cmd_unregister(PurpleCmdId id) 99 void purple_cmd_unregister(PurpleCmdId id)
98 { 100 {
99 PurpleCmd *c; 101 PurpleCmd *c;
100 GList *l; 102 GList *l;
101 103 PurpleCommandsUiOps *ops;
102 for (l = cmds; l; l = l->next) { 104
103 c = l->data; 105 l = g_list_find_custom(cmds, GUINT_TO_POINTER(id), purple_cmd_cmp_id);
104 106 if (!l) {
105 if (c->id == id) { 107 return;
106 PurpleCommandsUiOps *ops = purple_cmds_get_ui_ops(); 108 }
107 if (ops && ops->unregister_command) 109
108 ops->unregister_command(c->cmd, c->protocol_id); 110 c = l->data;
109 111
110 cmds = g_list_delete_link(cmds, l); 112 ops = purple_cmds_get_ui_ops();
111 purple_signal_emit(purple_cmds_get_handle(), "cmd-removed", c->cmd); 113 if (ops && ops->unregister_command) {
112 purple_cmd_free(c); 114 ops->unregister_command(c->cmd, c->protocol_id);
113 return; 115 }
114 } 116
115 } 117 cmds = g_list_delete_link(cmds, l);
118 purple_signal_emit(purple_cmds_get_handle(), "cmd-removed", c->cmd);
119 purple_cmd_free(c);
116 } 120 }
117 121
118 /* 122 /*
119 * This sets args to a NULL-terminated array of strings. It should 123 * This sets args to a NULL-terminated array of strings. It should
120 * be freed using g_strfreev(). 124 * be freed using g_strfreev().
199 } 203 }
200 s = g_utf8_next_char(s); 204 s = g_utf8_next_char(s);
201 } 205 }
202 } 206 }
203 207
208 static gboolean
209 is_right_type(PurpleCmd *cmd, PurpleConversation *conv)
210 {
211 return (PURPLE_IS_IM_CONVERSATION(conv) && (cmd->flags & PURPLE_CMD_FLAG_IM))
212 || (PURPLE_IS_CHAT_CONVERSATION(conv) && (cmd->flags & PURPLE_CMD_FLAG_CHAT));
213 }
214
215 static gboolean
216 is_right_protocol(PurpleCmd *cmd, PurpleConversation *conv)
217 {
218 const gchar *protocol_id = purple_account_get_protocol_id(purple_conversation_get_account(conv));
219
220 return !(cmd->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY)
221 || purple_strequal(cmd->protocol_id, protocol_id);
222 }
223
204 PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmdline, 224 PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmdline,
205 const gchar *markup, gchar **error) 225 const gchar *markup, gchar **error)
206 { 226 {
207 PurpleCmd *c;
208 GList *l;
209 gchar *err = NULL; 227 gchar *err = NULL;
210 gboolean is_im = TRUE;
211 gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_protocol = FALSE; 228 gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_protocol = FALSE;
212 const gchar *protocol_id;
213 gchar **args = NULL;
214 gchar *cmd, *rest, *mrest; 229 gchar *cmd, *rest, *mrest;
215 PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE; 230 PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE;
216 231
217 *error = NULL; 232 *error = NULL;
218 protocol_id = purple_account_get_protocol_id(purple_conversation_get_account(conv));
219
220 if (PURPLE_IS_CHAT_CONVERSATION(conv))
221 is_im = FALSE;
222 233
223 rest = strchr(cmdline, ' '); 234 rest = strchr(cmdline, ' ');
224 if (rest) { 235 if (rest) {
225 cmd = g_strndup(cmdline, rest - cmdline); 236 cmd = g_strndup(cmdline, rest - cmdline);
226 rest++; 237 rest++;
230 } 241 }
231 242
232 mrest = g_strdup(markup); 243 mrest = g_strdup(markup);
233 purple_cmd_strip_cmd_from_markup(mrest); 244 purple_cmd_strip_cmd_from_markup(mrest);
234 245
235 for (l = cmds; l; l = l->next) { 246 for (GList *l = cmds; l; l = l->next) {
236 c = l->data; 247 PurpleCmd *c = l->data;
248 gchar **args = NULL;
237 249
238 if (!purple_strequal(c->cmd, cmd)) 250 if (!purple_strequal(c->cmd, cmd))
239 continue; 251 continue;
240 252
241 found = TRUE; 253 found = TRUE;
242 254
243 if (is_im) 255 if (!is_right_type(c, conv)) {
244 if (!(c->flags & PURPLE_CMD_FLAG_IM)) 256 continue;
245 continue; 257 }
246 if (!is_im)
247 if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
248 continue;
249 258
250 right_type = TRUE; 259 right_type = TRUE;
251 260
252 if ((c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) && 261 if (!is_right_protocol(c, conv)) {
253 !purple_strequal(c->protocol_id, protocol_id)) 262 continue;
254 continue; 263 }
255 264
256 right_protocol = TRUE; 265 right_protocol = TRUE;
257 266
258 /* this checks the allow bad args flag for us */ 267 /* this checks the allow bad args flag for us */
259 if (!purple_cmd_parse_args(c, rest, mrest, &args)) { 268 if (!purple_cmd_parse_args(c, rest, mrest, &args)) {
260 g_strfreev(args); 269 g_strfreev(args);
261 args = NULL;
262 continue; 270 continue;
263 } 271 }
264 272
265 tried_cmd = TRUE; 273 tried_cmd = TRUE;
266 ret = c->func(conv, cmd, args, &err, c->data); 274 ret = c->func(conv, cmd, args, &err, c->data);
275 g_strfreev(args);
267 if (ret == PURPLE_CMD_RET_CONTINUE) { 276 if (ret == PURPLE_CMD_RET_CONTINUE) {
268 g_free(err); 277 g_free(err);
269 err = NULL; 278 err = NULL;
270 g_strfreev(args); 279 continue;
271 args = NULL; 280 }
272 continue; 281
273 } else { 282 break;
274 break; 283 }
275 } 284
276
277 }
278
279 g_strfreev(args);
280 g_free(cmd); 285 g_free(cmd);
281 g_free(mrest); 286 g_free(mrest);
282 287
283 if (!found) 288 if (!found)
284 return PURPLE_CMD_STATUS_NOT_FOUND; 289 return PURPLE_CMD_STATUS_NOT_FOUND;
288 if (!right_protocol) 293 if (!right_protocol)
289 return PURPLE_CMD_STATUS_WRONG_PROTOCOL; 294 return PURPLE_CMD_STATUS_WRONG_PROTOCOL;
290 if (!tried_cmd) 295 if (!tried_cmd)
291 return PURPLE_CMD_STATUS_WRONG_ARGS; 296 return PURPLE_CMD_STATUS_WRONG_ARGS;
292 297
293 if (ret == PURPLE_CMD_RET_OK) { 298 if (ret != PURPLE_CMD_RET_OK) {
294 return PURPLE_CMD_STATUS_OK;
295 } else {
296 *error = err; 299 *error = err;
297 if (ret == PURPLE_CMD_RET_CONTINUE) 300 if (ret == PURPLE_CMD_RET_CONTINUE)
298 return PURPLE_CMD_STATUS_NOT_FOUND; 301 return PURPLE_CMD_STATUS_NOT_FOUND;
299 else 302 else
300 return PURPLE_CMD_STATUS_FAILED; 303 return PURPLE_CMD_STATUS_FAILED;
301 } 304 }
302 305
306 return PURPLE_CMD_STATUS_OK;
303 } 307 }
304 308
305 gboolean purple_cmd_execute(PurpleCmdId id, PurpleConversation *conv, 309 gboolean purple_cmd_execute(PurpleCmdId id, PurpleConversation *conv,
306 const gchar *cmdline) 310 const gchar *cmdline)
307 { 311 {
309 PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE; 313 PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE;
310 GList *l = NULL; 314 GList *l = NULL;
311 gchar *err = NULL; 315 gchar *err = NULL;
312 gchar **args = NULL; 316 gchar **args = NULL;
313 317
314 for(l = cmds; l; l = l->next) { 318 l = g_list_find_custom(cmds, GUINT_TO_POINTER(id), purple_cmd_cmp_id);
315 cmd = (PurpleCmd*)l->data; 319 if (!l) {
316
317 if(cmd->id == id) {
318 break;
319 }
320 cmd = NULL;
321 }
322 if(cmd == NULL) {
323 return FALSE; 320 return FALSE;
324 } 321 }
325 322
326 if (PURPLE_IS_IM_CONVERSATION(conv)) { 323 cmd = l->data;
327 if (!(cmd->flags & PURPLE_CMD_FLAG_IM)) 324
328 return FALSE; 325 if (!is_right_type(cmd, conv)) {
329 }
330 else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
331 if (!(cmd->flags & PURPLE_CMD_FLAG_CHAT))
332 return FALSE;
333 }
334 else
335 return FALSE; 326 return FALSE;
327 }
336 328
337 /* XXX: Don't worry much about the markup version of the command 329 /* XXX: Don't worry much about the markup version of the command
338 line, there's not a single use case... */ 330 line, there's not a single use case... */
339 /* this checks the allow bad args flag for us */ 331 /* this checks the allow bad args flag for us */
340 if (!purple_cmd_parse_args(cmd, cmdline, cmdline, &args)) { 332 if (!purple_cmd_parse_args(cmd, cmdline, cmdline, &args)) {
351 } 343 }
352 344
353 GList *purple_cmd_list(PurpleConversation *conv) 345 GList *purple_cmd_list(PurpleConversation *conv)
354 { 346 {
355 GList *ret = NULL; 347 GList *ret = NULL;
356 PurpleCmd *c; 348
357 GList *l; 349 for (GList *l = cmds; l; l = l->next) {
358 350 PurpleCmd *c = l->data;
359 for (l = cmds; l; l = l->next) { 351
360 c = l->data; 352 if (conv && (!is_right_type(c, conv) || !is_right_protocol(c, conv))) {
361 353 continue;
362 if (conv && PURPLE_IS_IM_CONVERSATION(conv)) 354 }
363 if (!(c->flags & PURPLE_CMD_FLAG_IM))
364 continue;
365 if (conv && PURPLE_IS_CHAT_CONVERSATION(conv))
366 if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
367 continue;
368
369 if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) &&
370 !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
371 continue;
372 355
373 ret = g_list_append(ret, c->cmd); 356 ret = g_list_append(ret, c->cmd);
374 } 357 }
375 358
376 ret = g_list_sort(ret, (GCompareFunc)strcmp); 359 ret = g_list_sort(ret, (GCompareFunc)strcmp);
380 363
381 364
382 GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd) 365 GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd)
383 { 366 {
384 GList *ret = NULL; 367 GList *ret = NULL;
385 PurpleCmd *c; 368
386 GList *l; 369 for (GList *l = cmds; l; l = l->next) {
387 370 PurpleCmd *c = l->data;
388 for (l = cmds; l; l = l->next) {
389 c = l->data;
390 371
391 if (cmd && !purple_strequal(cmd, c->cmd)) 372 if (cmd && !purple_strequal(cmd, c->cmd))
392 continue; 373 continue;
393 374
394 if (conv && PURPLE_IS_IM_CONVERSATION(conv)) 375 if (conv && (!is_right_type(c, conv) || !is_right_protocol(c, conv))) {
395 if (!(c->flags & PURPLE_CMD_FLAG_IM)) 376 continue;
396 continue; 377 }
397 if (conv && PURPLE_IS_CHAT_CONVERSATION(conv))
398 if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
399 continue;
400
401 if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) &&
402 !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
403 continue;
404 378
405 ret = g_list_append(ret, c->help); 379 ret = g_list_append(ret, c->help);
406 } 380 }
407 381
408 ret = g_list_sort(ret, (GCompareFunc)strcmp); 382 ret = g_list_sort(ret, (GCompareFunc)strcmp);

mercurial