diff --git a/ChangeLog b/ChangeLog index 1c228d275..4f79228ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ WeeChat ChangeLog ================= Sébastien Helleu -v0.3.3-dev, 2010-06-18 +v0.3.3-dev, 2010-07-05 Version 0.3.3 (under dev!) @@ -16,6 +16,7 @@ Version 0.3.3 (under dev!) * core: fix crash with hook_process (when timer is called on a deleted hook process) * core: fix display bug with attributes like underlined in bars (bug #29889) +* core: add hashtables with new functions in plugin API * api: add function "string_expand_home", fix bug with replacement of home in paths * irc: use empty real name by default in config, instead of reading real name diff --git a/src/core/wee-command.c b/src/core/wee-command.c index f0d6af13e..0bf9b5eab 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -39,6 +39,7 @@ #include "wee-config.h" #include "wee-config-file.h" #include "wee-debug.h" +#include "wee-hashtable.h" #include "wee-hook.h" #include "wee-input.h" #include "wee-list.h" @@ -495,6 +496,28 @@ command_bar (void *data, struct t_gui_buffer *buffer, return WEECHAT_RC_ERROR; } +/* + * command_buffer_display_localvar: display local variable for a buffer + */ + +void +command_buffer_display_localvar (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) +{ + /* make C compiler happy */ + (void) data; + (void) hashtable; + + if (key && value) + { + gui_chat_printf (NULL, + " %s: \"%s\"", + (const char *)key, + (const char *)value); + } +} + /* * command_buffer: manage buffers */ @@ -504,7 +527,6 @@ command_buffer (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_gui_buffer *ptr_buffer; - struct t_gui_buffer_local_var *ptr_local_var; long number, number1, number2; char *error, *value, *pos, *str_number1, *pos_number2; int i, target_buffer; @@ -789,19 +811,14 @@ command_buffer (void *data, struct t_gui_buffer *buffer, /* display local variables on buffer */ if (string_strcasecmp (argv[1], "localvar") == 0) { - if (buffer->local_variables) + if (buffer->local_variables + && (buffer->local_variables->items_count > 0)) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Local variables for buffer \"%s\":"), buffer->name); - for (ptr_local_var = buffer->local_variables; ptr_local_var; - ptr_local_var = ptr_local_var->next_var) - { - gui_chat_printf (NULL, - " %s: \"%s\"", - ptr_local_var->name, - ptr_local_var->value); - } + hashtable_map (buffer->local_variables, + &command_buffer_display_localvar, NULL); } else { diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c index e967fc6a6..bc44f1c13 100644 --- a/src/core/wee-hashtable.c +++ b/src/core/wee-hashtable.c @@ -31,12 +31,13 @@ #include "weechat.h" #include "wee-hashtable.h" +#include "wee-infolist.h" #include "wee-log.h" #include "wee-string.h" -#include "../plugins/weechat-plugin.h" +#include "../plugins/plugin.h" -char *hashtable_type_names[HASHTABLE_NUM_TYPES] = +char *hashtable_type_string[HASHTABLE_NUM_TYPES] = { "integer", "string", "pointer", "buffer", "time" }; @@ -54,7 +55,7 @@ hashtable_get_type (const char *type) for (i = 0; i < HASHTABLE_NUM_TYPES; i++) { - if (string_strcasecmp (hashtable_type_names[i], type) == 0) + if (string_strcasecmp (hashtable_type_string[i], type) == 0) return i; } @@ -247,7 +248,10 @@ hashtable_set_with_size (struct t_hashtable *hashtable, /* replace value if item is already in hash table */ if (ptr_item && (hashtable->callback_keycmp (hashtable, key, ptr_item->key) == 0)) { - ptr_item->value = value; + hashtable_free_type (hashtable->type_values, ptr_item->value); + hashtable_alloc_type (hashtable->type_values, + value, value_size, + &ptr_item->value, &ptr_item->value_size); return 1; } @@ -398,6 +402,74 @@ hashtable_get_integer (struct t_hashtable *hashtable, const char *property) return 0; } +/* + * hashtable_add_to_infolist: add hashtable keys and values to infolist + * return 1 if ok, 0 if error + */ + +int +hashtable_add_to_infolist (struct t_hashtable *hashtable, + struct t_infolist_item *infolist_item, + const char *prefix) +{ + int i, item_number; + struct t_hashtable_item *ptr_item; + char option_name[128]; + + if (!hashtable || (hashtable->type_keys != HASHTABLE_STRING) + || !infolist_item || !prefix) + return 0; + + item_number = 0; + for (i = 0; i < hashtable->size; i++) + { + for (ptr_item = hashtable->htable[i]; ptr_item; + ptr_item = ptr_item->next_item) + { + snprintf (option_name, sizeof (option_name), + "%s_name_%05d", prefix, item_number); + if (!infolist_new_var_string (infolist_item, option_name, + (const char *)ptr_item->key)) + return 0; + snprintf (option_name, sizeof (option_name), + "%s_value_%05d", prefix, item_number); + switch (hashtable->type_values) + { + case HASHTABLE_INTEGER: + if (!infolist_new_var_integer (infolist_item, option_name, + *((int *)ptr_item->value))) + return 0; + break; + case HASHTABLE_STRING: + if (!infolist_new_var_string (infolist_item, option_name, + (const char *)ptr_item->value)) + return 0; + break; + case HASHTABLE_POINTER: + if (!infolist_new_var_pointer (infolist_item, option_name, + ptr_item->value)) + return 0; + break; + case HASHTABLE_BUFFER: + if (!infolist_new_var_buffer (infolist_item, option_name, + ptr_item->value, + ptr_item->value_size)) + return 0; + break; + case HASHTABLE_TIME: + if (!infolist_new_var_time (infolist_item, option_name, + *((time_t *)ptr_item->value))) + return 0; + break; + case HASHTABLE_NUM_TYPES: + break; + } + item_number++; + } + } + return 1; +} + /* * hashtable_remove_item: remove an item from hashmap */ @@ -488,8 +560,12 @@ hashtable_print_log (struct t_hashtable *hashtable, const char *name) log_printf (" size . . . . . . . . . : %d", hashtable->size); log_printf (" htable . . . . . . . . : 0x%lx", hashtable->htable); log_printf (" items_count. . . . . . : %d", hashtable->items_count); - log_printf (" type_keys. . . . . . . : %d", hashtable->type_keys); - log_printf (" type_values. . . . . . : %d", hashtable->type_values); + log_printf (" type_keys. . . . . . . : %d (%s)", + hashtable->type_keys, + hashtable_type_string[hashtable->type_keys]); + log_printf (" type_values. . . . . . : %d (%s)", + hashtable->type_values, + hashtable_type_string[hashtable->type_values]); log_printf (" callback_hash_key. . . : 0x%lx", hashtable->callback_hash_key); log_printf (" callback_keycmp. . . . : 0x%lx", hashtable->callback_keycmp); diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h index 392cbe416..ab36cdff5 100644 --- a/src/core/wee-hashtable.h +++ b/src/core/wee-hashtable.h @@ -21,6 +21,7 @@ #define __WEECHAT_HASHTABLE_H 1 struct t_hashtable; +struct t_infolist_item; typedef unsigned int (t_hashtable_hash_key)(struct t_hashtable *hashtable, const void *key); @@ -114,6 +115,9 @@ extern void hashtable_map (struct t_hashtable *hashtable, void *callback_map_data); extern int hashtable_get_integer (struct t_hashtable *hashtable, const char *property); +extern int hashtable_add_to_infolist (struct t_hashtable *hashtable, + struct t_infolist_item *infolist_item, + const char *prefix); extern void hashtable_remove (struct t_hashtable *hashtable, const void *key); extern void hashtable_remove_all (struct t_hashtable *hashtable); extern void hashtable_free (struct t_hashtable *hashtable); diff --git a/src/core/wee-list.c b/src/core/wee-list.c index 25e182f0a..599b93a4e 100644 --- a/src/core/wee-list.c +++ b/src/core/wee-list.c @@ -32,7 +32,7 @@ #include "wee-list.h" #include "wee-log.h" #include "wee-string.h" -#include "../plugins/weechat-plugin.h" +#include "../plugins/plugin.h" /* diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index 524277207..cf85559c8 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -31,6 +31,7 @@ #include "../core/weechat.h" #include "../core/wee-config.h" +#include "../core/wee-hashtable.h" #include "../core/wee-hook.h" #include "../core/wee-infolist.h" #include "../core/wee-log.h" @@ -593,7 +594,7 @@ char * gui_bar_item_default_input_prompt (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { - struct t_gui_buffer_local_var *local_var_nick; + const char *nick; /* make C compiler happy */ (void) data; @@ -602,11 +603,12 @@ gui_bar_item_default_input_prompt (void *data, struct t_gui_bar_item *item, if (!window) window = gui_current_window; - local_var_nick = gui_buffer_local_var_search (window->buffer, "nick"); - if (!local_var_nick || !local_var_nick->value) + nick = (const char *)hashtable_get (window->buffer->local_variables, + "nick"); + if (!nick) return NULL; - return strdup (local_var_nick->value); + return strdup (nick); } /* diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index 5c77a2fcd..8b4d68291 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -36,6 +36,7 @@ #include "../core/weechat.h" #include "../core/wee-config.h" +#include "../core/wee-hashtable.h" #include "../core/wee-hook.h" #include "../core/wee-infolist.h" #include "../core/wee-list.h" @@ -124,77 +125,25 @@ gui_buffer_find_pos (struct t_gui_buffer *buffer) return NULL; } -/* - * gui_buffer_local_var_search: search a local variable with name - */ - -struct t_gui_buffer_local_var * -gui_buffer_local_var_search (struct t_gui_buffer *buffer, const char *name) -{ - struct t_gui_buffer_local_var *ptr_local_var; - - if (!buffer || !name) - return NULL; - - for (ptr_local_var = buffer->local_variables; ptr_local_var; - ptr_local_var = ptr_local_var->next_var) - { - if (strcmp (ptr_local_var->name, name) == 0) - return ptr_local_var; - } - - /* local variable not found */ - return NULL; -} - /* * gui_buffer_local_var_add: add a new local variable to a buffer */ -struct t_gui_buffer_local_var * +void gui_buffer_local_var_add (struct t_gui_buffer *buffer, const char *name, const char *value) { - struct t_gui_buffer_local_var *new_local_var; + void *ptr_value; - if (!buffer || !name || !value) - return NULL; + if (!buffer || !buffer->local_variables || !name || !value) + return; - new_local_var = gui_buffer_local_var_search (buffer, name); - if (new_local_var) - { - if (new_local_var->name) - free (new_local_var->name); - if (new_local_var->value) - free (new_local_var->value); - new_local_var->name = strdup (name); - new_local_var->value = strdup (value); - - hook_signal_send ("buffer_localvar_changed", - WEECHAT_HOOK_SIGNAL_POINTER, buffer); - } - else - { - new_local_var = malloc (sizeof (*new_local_var)); - if (new_local_var) - { - new_local_var->name = strdup (name); - new_local_var->value = strdup (value); - - new_local_var->prev_var = buffer->last_local_var; - new_local_var->next_var = NULL; - if (buffer->local_variables) - buffer->last_local_var->next_var = new_local_var; - else - buffer->local_variables = new_local_var; - buffer->last_local_var = new_local_var; - - hook_signal_send ("buffer_localvar_added", - WEECHAT_HOOK_SIGNAL_POINTER, buffer); - } - } - - return new_local_var; + ptr_value = hashtable_get (buffer->local_variables, name); + hashtable_set (buffer->local_variables, + (void *)name, (void *)value); + hook_signal_send ((ptr_value) ? + "buffer_localvar_changed" : "buffer_localvar_added", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); } /* @@ -202,32 +151,20 @@ gui_buffer_local_var_add (struct t_gui_buffer *buffer, const char *name, */ void -gui_buffer_local_var_remove (struct t_gui_buffer *buffer, - struct t_gui_buffer_local_var *local_var) +gui_buffer_local_var_remove (struct t_gui_buffer *buffer, const char *name) { - if (!buffer || !local_var) + void *ptr_value; + + if (!buffer || !buffer->local_variables || !name) return; - /* free data */ - if (local_var->name) - free (local_var->name); - if (local_var->value) - free (local_var->value); - - /* remove local variable from list */ - if (local_var->prev_var) - (local_var->prev_var)->next_var = local_var->next_var; - if (local_var->next_var) - (local_var->next_var)->prev_var = local_var->prev_var; - if (buffer->local_variables == local_var) - buffer->local_variables = local_var->next_var; - if (buffer->last_local_var == local_var) - buffer->last_local_var = local_var->prev_var; - - free (local_var); - - hook_signal_send ("buffer_localvar_removed", - WEECHAT_HOOK_SIGNAL_POINTER, buffer); + ptr_value = hashtable_get (buffer->local_variables, name); + if (ptr_value) + { + hashtable_remove (buffer->local_variables, name); + hook_signal_send ("buffer_localvar_removed", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); + } } /* @@ -237,12 +174,11 @@ gui_buffer_local_var_remove (struct t_gui_buffer *buffer, void gui_buffer_local_var_remove_all (struct t_gui_buffer *buffer) { - if (buffer) + if (buffer && buffer->local_variables) { - while (buffer->local_variables) - { - gui_buffer_local_var_remove (buffer, buffer->local_variables); - } + hashtable_remove_all (buffer->local_variables); + hook_signal_send ("buffer_localvar_removed", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); } } @@ -519,10 +455,15 @@ gui_buffer_new (struct t_weechat_plugin *plugin, new_buffer->keys_count = 0; /* local variables */ - new_buffer->local_variables = NULL; - new_buffer->last_local_var = NULL; - gui_buffer_local_var_add (new_buffer, "plugin", plugin_get_name (plugin)); - gui_buffer_local_var_add (new_buffer, "name", name); + new_buffer->local_variables = hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + hashtable_set (new_buffer->local_variables, + "plugin", (void *)plugin_get_name (plugin)); + hashtable_set (new_buffer->local_variables, + "name", (void *)name); /* add buffer to buffers list */ first_buffer_creation = (gui_buffers == NULL); @@ -590,8 +531,7 @@ gui_buffer_string_replace_local_var (struct t_gui_buffer *buffer, { int length, length_var, index_string, index_result; char *result, *local_var; - const char *pos_end_name; - struct t_gui_buffer_local_var *ptr_local_var; + const char *pos_end_name, *ptr_value; if (!string) return NULL; @@ -623,11 +563,11 @@ gui_buffer_string_replace_local_var (struct t_gui_buffer *buffer, pos_end_name - (string + index_string + 1)); if (local_var) { - ptr_local_var = gui_buffer_local_var_search (buffer, - local_var); - if (ptr_local_var) + ptr_value = (const char *)hashtable_get (buffer->local_variables, + local_var); + if (ptr_value) { - length_var = strlen (ptr_local_var->value); + length_var = strlen (ptr_value); length += length_var; result = realloc (result, length); if (!result) @@ -635,7 +575,7 @@ gui_buffer_string_replace_local_var (struct t_gui_buffer *buffer, free (local_var); return NULL; } - strcpy (result + index_result, ptr_local_var->value); + strcpy (result + index_result, ptr_value); index_result += length_var; index_string += strlen (local_var) + 1; } @@ -777,7 +717,7 @@ gui_buffer_get_integer (struct t_gui_buffer *buffer, const char *property) const char * gui_buffer_get_string (struct t_gui_buffer *buffer, const char *property) { - struct t_gui_buffer_local_var *ptr_local_var; + const char *ptr_value; if (buffer && property) { @@ -799,9 +739,10 @@ gui_buffer_get_string (struct t_gui_buffer *buffer, const char *property) return buffer->highlight_tags; else if (string_strncasecmp (property, "localvar_", 9) == 0) { - ptr_local_var = gui_buffer_local_var_search (buffer, property + 9); - if (ptr_local_var) - return ptr_local_var->value; + ptr_value = (const char *)hashtable_get (buffer->local_variables, + property + 9); + if (ptr_value) + return ptr_value; } } @@ -1185,7 +1126,6 @@ gui_buffer_set (struct t_gui_buffer *buffer, const char *property, { long number; char *error; - struct t_gui_buffer_local_var *ptr_local_var; if (!property || !value) return; @@ -1356,9 +1296,7 @@ gui_buffer_set (struct t_gui_buffer *buffer, const char *property, } else if (string_strncasecmp (property, "localvar_del_", 13) == 0) { - ptr_local_var = gui_buffer_local_var_search (buffer, property + 13); - if (ptr_local_var) - gui_buffer_local_var_remove (buffer, ptr_local_var); + gui_buffer_local_var_remove (buffer, property + 13); } } @@ -2682,7 +2620,6 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, { struct t_infolist_item *ptr_item; struct t_gui_key *ptr_key; - struct t_gui_buffer_local_var *ptr_local_var; char option_name[64]; int i; @@ -2780,20 +2717,8 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, } if (!infolist_new_var_integer (ptr_item, "keys_count", buffer->keys_count)) return 0; - i = 0; - for (ptr_local_var = buffer->local_variables; ptr_local_var; - ptr_local_var = ptr_local_var->next_var) - { - snprintf (option_name, sizeof (option_name), "localvar_name_%05d", i); - if (!infolist_new_var_string (ptr_item, option_name, - ptr_local_var->name)) - return 0; - snprintf (option_name, sizeof (option_name), "localvar_value_%05d", i); - if (!infolist_new_var_string (ptr_item, option_name, - ptr_local_var->value)) - return 0; - i++; - } + if (!hashtable_add_to_infolist (buffer->local_variables, ptr_item, "localvar")) + return 0; return 1; } @@ -2875,7 +2800,6 @@ void gui_buffer_print_log () { struct t_gui_buffer *ptr_buffer; - struct t_gui_buffer_local_var *ptr_local_var; struct t_gui_line *ptr_line; struct t_gui_buffer_visited *ptr_buffer_visited; struct t_gui_input_undo *ptr_undo; @@ -2957,7 +2881,6 @@ gui_buffer_print_log () log_printf (" last_key . . . . . . . : 0x%lx", ptr_buffer->last_key); log_printf (" keys_count . . . . . . : %d", ptr_buffer->keys_count); log_printf (" local_variables. . . . : 0x%lx", ptr_buffer->local_variables); - log_printf (" last_local_var . . . . : 0x%lx", ptr_buffer->last_local_var); log_printf (" prev_buffer. . . . . . : 0x%lx", ptr_buffer->prev_buffer); log_printf (" next_buffer. . . . . . : 0x%lx", ptr_buffer->next_buffer); @@ -2967,20 +2890,11 @@ gui_buffer_print_log () log_printf (" => keys:"); gui_keyboard_print_log (ptr_buffer); } - + if (ptr_buffer->local_variables) { - log_printf (""); - log_printf (" => local_variables:"); - for (ptr_local_var = ptr_buffer->local_variables; ptr_local_var; - ptr_local_var = ptr_local_var->next_var) - { - log_printf (""); - log_printf (" [local variable (addr:0x%lx)]", - ptr_local_var); - log_printf (" name . . . . . . . : '%s'", ptr_local_var->name); - log_printf (" value. . . . . . . : '%s'", ptr_local_var->value); - } + hashtable_print_log (ptr_buffer->local_variables, + "local_variables"); } log_printf (""); diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h index 32993c105..20cd4e8f6 100644 --- a/src/gui/gui-buffer.h +++ b/src/gui/gui-buffer.h @@ -20,6 +20,7 @@ #ifndef __WEECHAT_GUI_BUFFER_H #define __WEECHAT_GUI_BUFFER_H 1 +struct t_hashtable; struct t_gui_window; struct t_infolist; @@ -49,14 +50,6 @@ enum t_gui_buffer_notify /* buffer structures */ -struct t_gui_buffer_local_var -{ - char *name; /* variable name */ - char *value; /* value */ - struct t_gui_buffer_local_var *prev_var; /* link to previous variable */ - struct t_gui_buffer_local_var *next_var; /* link to next variable */ -}; - struct t_gui_input_undo { char *data; /* content of input buffer */ @@ -176,8 +169,7 @@ struct t_gui_buffer int keys_count; /* number of keys in buffer */ /* local variables */ - struct t_gui_buffer_local_var *local_variables; /* local variables */ - struct t_gui_buffer_local_var *last_local_var; /* last local variable */ + struct t_hashtable *local_variables; /* local variables */ /* link to previous/next buffer */ struct t_gui_buffer *prev_buffer; /* link to previous buffer */ @@ -208,8 +200,6 @@ extern char *gui_buffer_properties_set[]; /* buffer functions */ -extern struct t_gui_buffer_local_var *gui_buffer_local_var_search (struct t_gui_buffer *buffer, - const char *name); extern void gui_buffer_notify_set_all (); extern struct t_gui_buffer *gui_buffer_new (struct t_weechat_plugin *plugin, const char *name, diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index b1a37e53c..5317e4f14 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -527,6 +527,7 @@ plugin_load (const char *filename) new_plugin->hashtable_get = &hashtable_get; new_plugin->hashtable_map = &hashtable_map; new_plugin->hashtable_get_integer = &hashtable_get_integer; + new_plugin->hashtable_add_to_infolist = &hashtable_add_to_infolist; new_plugin->hashtable_remove = &hashtable_remove; new_plugin->hashtable_remove_all = &hashtable_remove_all; new_plugin->hashtable_free = &hashtable_free; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index feb1f8d3a..8e26cad72 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -34,6 +34,7 @@ struct t_gui_bar; struct t_gui_bar_item; struct t_gui_completion; struct t_infolist; +struct t_infolist_item; struct t_weelist; struct t_hashtable; struct timeval; @@ -272,6 +273,9 @@ struct t_weechat_plugin void *callback_map_data); int (*hashtable_get_integer) (struct t_hashtable *hashtable, const char *property); + int (*hashtable_add_to_infolist) (struct t_hashtable *hashtable, + struct t_infolist_item *infolist_item, + const char *prefix); void (*hashtable_remove) (struct t_hashtable *hashtable, const void *key); void (*hashtable_remove_all) (struct t_hashtable *hashtable); void (*hashtable_free) (struct t_hashtable *hashtable); @@ -882,6 +886,11 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->hashtable_map(__hashtable, __cb_map, __cb_map_data) #define weechat_hashtable_get_integer(__hashtable, __property) \ weechat_plugin->hashtable_get_integer(__hashtable, __property) +#define weechat_hashtable_add_to_infolist(__hashtable, __infolist_item, \ + __prefix) \ + weechat_plugin->hashtable_add_to_infolist(__hashtable, \ + __infolist_item, \ + __prefix) #define weechat_hashtable_remove(__hashtable, __key) \ weechat_plugin->hashtable_remove(__hashtable, __key) #define weechat_hashtable_remove_all(__hashtable) \