diff --git a/src/twc-chat.c b/src/twc-chat.c index 97921b8..4da921e 100644 --- a/src/twc-chat.c +++ b/src/twc-chat.c @@ -24,6 +24,7 @@ #include #include +#include "twc-config.h" #include "twc-list.h" #include "twc-message-queue.h" #include "twc-profile.h" @@ -57,6 +58,10 @@ twc_chat_new(struct t_twc_profile *profile, const char *name) chat->profile = profile; chat->friend_number = chat->group_number = -1; chat->nicks = NULL; + chat->ids = NULL; + chat->completion = NULL; + chat->last_search = NULL; + chat->prev_comp = NULL; size_t full_name_size = strlen(profile->name) + 1 + strlen(name) + 1; char *full_name = malloc(full_name_size); @@ -137,6 +142,8 @@ twc_chat_new_group(struct t_twc_profile *profile, int32_t group_number) chat->nicklist_group = weechat_nicklist_add_group(chat->buffer, NULL, NULL, NULL, true); chat->nicks = weechat_list_new(); + chat->ids = weechat_list_new(); + chat->completion = weechat_list_new(); weechat_buffer_set(chat->buffer, "nicklist", "1"); } @@ -274,6 +281,54 @@ twc_chat_search_buffer(struct t_gui_buffer *buffer) return NULL; } +/** + * Set a prefix to a nickname in the nicklist of a chat. + */ +void +twc_chat_update_prefix(struct t_twc_chat *chat, const char *id, + const char *prefix, const char *prefix_color) +{ + struct t_gui_nick_group *ptr_group = NULL; + struct t_gui_nick *ptr_nick = NULL; + + weechat_nicklist_get_next_item(chat->buffer, &ptr_group, &ptr_nick); + while (ptr_group || ptr_nick) + { + if (ptr_nick) + { + const char *name_field = weechat_nicklist_nick_get_string( + chat->buffer, ptr_nick, "name"); + size_t short_id_length = + weechat_config_integer(twc_config_short_id_size); + if (!weechat_strncasecmp(id, name_field + sizeof(char), + short_id_length)) + { + weechat_nicklist_nick_set(chat->buffer, ptr_nick, "prefix", + prefix); + weechat_nicklist_nick_set(chat->buffer, ptr_nick, + "prefix_color", prefix_color); + weechat_nicklist_nick_set(chat->buffer, ptr_nick, "color", + "default"); + return; + } + } + weechat_nicklist_get_next_item(chat->buffer, &ptr_group, &ptr_nick); + } +} + +/** + * Update prefix for a certain nickname structure pointer. + */ +void +twc_chat_update_prefix_by_nick(struct t_gui_buffer *buffer, + struct t_gui_nick *nick, const char *prefix, + const char *prefix_color) +{ + weechat_nicklist_nick_set(buffer, nick, "prefix", prefix); + weechat_nicklist_nick_set(buffer, nick, "prefix_color", prefix_color); + weechat_nicklist_nick_set(buffer, nick, "color", "default"); +} + /** * Print a chat message to a chat's buffer. */ @@ -395,6 +450,18 @@ twc_chat_free(struct t_twc_chat *chat) weechat_list_remove_all(chat->nicks); weechat_list_free(chat->nicks); } + if (chat->ids) + { + weechat_list_remove_all(chat->ids); + weechat_list_free(chat->ids); + } + if (chat->completion) + { + weechat_list_remove_all(chat->completion); + weechat_list_free(chat->completion); + } + free(chat->last_search); + free(chat->prev_comp); free(chat); } diff --git a/src/twc-chat.h b/src/twc-chat.h index a37176e..836e8eb 100644 --- a/src/twc-chat.h +++ b/src/twc-chat.h @@ -39,6 +39,10 @@ struct t_twc_chat struct t_gui_nick_group *nicklist_group; struct t_weelist *nicks; + struct t_weelist *ids; + struct t_weelist *completion; + char *last_search; + char *prev_comp; }; struct t_twc_chat * @@ -52,6 +56,15 @@ twc_chat_search_group(struct t_twc_profile *profile, int32_t group_number, struct t_twc_chat * twc_chat_search_buffer(struct t_gui_buffer *target_buffer); +void +twc_chat_update_prefix(struct t_twc_chat *chat, const char *id, + const char *prefix, const char *prefix_color); + +void +twc_chat_update_prefix_by_nick(struct t_gui_buffer *buffer, + struct t_gui_nick *nick, const char *prefix, + const char *prefix_color); + enum t_twc_rc twc_chat_set_logging(struct t_twc_chat const *const chat, bool logging); diff --git a/src/twc-commands.c b/src/twc-commands.c index a3a0618..5ad92d4 100644 --- a/src/twc-commands.c +++ b/src/twc-commands.c @@ -1330,6 +1330,154 @@ twc_cmd_send(const void *pointer, void *data, struct t_gui_buffer *buffer, return WEECHAT_RC_OK; } +/** + * Custom completion for nicknames in groups. + */ +int +twc_input_complete(const void *pointer, void *data, struct t_gui_buffer *buffer, + const char *command) +{ + struct t_twc_chat *chat = twc_chat_search_buffer(buffer); + if (chat && chat->group_number >= 0) + { + const char *input = weechat_buffer_get_string(buffer, "input"); + if (!strcmp(input, "")) + return WEECHAT_RC_OK; + size_t last_search_len = + chat->last_search ? strlen(chat->last_search) : 0; + int cmp = strncmp(chat->last_search, input, last_search_len); + if (cmp || !last_search_len) + { + free(chat->last_search); + chat->last_search = strdup(input); + free(chat->prev_comp); + chat->prev_comp = NULL; + twc_starts_with(chat->nicks, chat->last_search, chat->completion); + } + + const char *comp = + twc_get_next_completion(chat->completion, chat->prev_comp); + if (!comp) + return WEECHAT_RC_OK; + + weechat_buffer_set(buffer, "completion_freeze", "1"); + + char *terminator = ": "; /* Probably put it in a config */ + char temp[strlen(comp) + strlen(terminator) + 1]; + sprintf(temp, "%s%s", comp, terminator); + weechat_buffer_set(buffer, "input", temp); + + int input_pos = weechat_buffer_get_integer(buffer, "input_length"); + int input_pos_str_size = snprintf(NULL, 0, "%d", input_pos); + char input_pos_str[input_pos_str_size + 1]; + snprintf(input_pos_str, input_pos_str_size + 1, "%d", input_pos); + weechat_buffer_set(buffer, "input_pos", input_pos_str); + + weechat_buffer_set(buffer, "completion_freeze", "0"); + + free(chat->prev_comp); + chat->prev_comp = strdup(comp); + return WEECHAT_RC_OK_EAT; + } + return WEECHAT_RC_OK; +} +/** + * Update a certain nick's prefix in all opened group chats + */ +void +twc_name_prefix_in_groupchats(struct t_twc_profile *profile, const char *id, + const char *prefix, const char *prefix_color) +{ + struct t_twc_list_item *item; + struct t_twc_chat *chat; + size_t index; + twc_list_foreach (profile->chats, index, item) + { + chat = (struct t_twc_chat *)(item->chat); + if ((chat->group_number) >= 0) + { + twc_chat_update_prefix(chat, id, prefix, prefix_color); + } + } +} + +/** + * Command /ignore callback. + */ +int +twc_cmd_ignore(const void *pointer, void *data, struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + struct t_twc_profile *profile = twc_profile_search_buffer(buffer); + TWC_CHECK_PROFILE(profile); + TWC_CHECK_PROFILE_LOADED(profile); + + /* list ignores */ + if ((argc == 1) || + ((argc == 2) && (weechat_strcasecmp(argv[1], "list") == 0))) + { + if (!weechat_list_size(profile->ignores)) + { + weechat_printf(profile->buffer, "ignore list is empty"); + return WEECHAT_RC_OK; + } + weechat_printf(profile->buffer, "ignore list:"); + size_t i = 0; + struct t_weelist_item *item; + for (item = weechat_list_get(profile->ignores, 0); item; + item = weechat_list_next(item)) + { + weechat_printf(profile->buffer, " [%d] %s", i, + weechat_list_string(item)); + i++; + } + return WEECHAT_RC_OK; + } + /* add ignore */ + + const char *id = argv_eol[2]; + struct t_weelist_item *item; + item = twc_is_id_ignored(profile, id); + + if (weechat_strcasecmp(argv[1], "add") == 0) + { + WEECHAT_COMMAND_MIN_ARGS(3, "add"); + if (!item) + { + weechat_list_add(profile->ignores, id, WEECHAT_LIST_POS_END, NULL); + weechat_printf(profile->buffer, + "%sID '%s' has been added to the ignore list", + weechat_prefix("action"), id); + twc_name_prefix_in_groupchats(profile, id, "-", "yellow"); + } + else + weechat_printf(profile->buffer, + "%sID '%s' is already in the ignore list", + weechat_prefix("error"), id); + return WEECHAT_RC_OK; + } + + /* delete ignore */ + if (weechat_strcasecmp(argv[1], "del") == 0) + { + WEECHAT_COMMAND_MIN_ARGS(3, "del"); + if (item) + { + weechat_list_remove(profile->ignores, item); + weechat_printf(profile->buffer, + "%sID '%s' has been deleted from the ignore list", + weechat_prefix("action"), id); + twc_name_prefix_in_groupchats(profile, id, " ", "default"); + } + else + weechat_printf(profile->buffer, + "%sthere's no ID '%s' in the ignore list", + weechat_prefix("error"), id); + return WEECHAT_RC_OK; + } + return WEECHAT_RC_ERROR; +} + /** * Register Tox-WeeChat commands. */ @@ -1421,6 +1569,9 @@ twc_commands_init() weechat_hook_command_run("/save", twc_cmd_save, NULL, NULL); + weechat_hook_command_run("/input complete_next", twc_input_complete, NULL, + NULL); + weechat_hook_command("status", "change your Tox status", "online|busy|away", "", NULL, twc_cmd_status, NULL, NULL); @@ -1464,4 +1615,16 @@ twc_commands_init() "%(filename)" " || %(tox_friend_name)|%(tox_friend_tox_id) %(filename)", twc_cmd_send, NULL, NULL); + weechat_hook_command("ignore", + "ommit messages from people with certain Tox IDs", + "list" + " || add " + " || del ", + "list: show the list of ignores\n" + "add: add an ID to the list\n" + "del: delete an ID from the list\n", + "list" + " || add %*" + " || del %*", + twc_cmd_ignore, NULL, NULL); } diff --git a/src/twc-config.c b/src/twc-config.c index 4b69d5e..f823f0e 100644 --- a/src/twc-config.c +++ b/src/twc-config.c @@ -35,9 +35,11 @@ struct t_config_file *twc_config_file = NULL; struct t_config_section *twc_config_section_look = NULL; struct t_config_section *twc_config_section_profile = NULL; struct t_config_section *twc_config_section_profile_default = NULL; +struct t_config_section *twc_config_section_ignore = NULL; struct t_config_option *twc_config_friend_request_message; struct t_config_option *twc_config_short_id_size; +struct t_config_option *twc_config_show_id; char *twc_profile_option_names[TWC_PROFILE_NUM_OPTIONS] = { "save_file", @@ -206,6 +208,80 @@ twc_config_profile_change_callback(const void *pointer, void *data, } } +/* + * Reads ignore option from configuration file. + * + * Returns: + * 1: OK + * 0: error + */ +int +twc_config_ignore_read_callback(const void *pointer, void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, const char *value) +{ + /* make C compiler happy */ + (void)pointer; + (void)data; + (void)config_file; + (void)section; + if (option_name) + { + char *profile_name = strrchr(option_name, '.'); + if (profile_name) + { + profile_name = strndup(option_name, + (profile_name - option_name) / sizeof(char)); + struct t_twc_profile *profile = + twc_profile_search_name(profile_name); + if (profile) + { + weechat_list_add(profile->ignores, value, WEECHAT_LIST_POS_END, + NULL); + } + free(profile_name); + } + } + return 1; +} + +/* + * Writes ignore section in tox configuration file. + */ +int +twc_config_ignore_write_callback(const void *pointer, void *data, + struct t_config_file *config_file, + const char *section_name) +{ + /* make C compiler happy */ + (void)pointer; + (void)data; + + if (!weechat_config_write_line(config_file, section_name, NULL)) + return WEECHAT_CONFIG_WRITE_ERROR; + + struct t_twc_list_item *item; + size_t index; + twc_list_foreach (twc_profiles, index, item) + { + size_t option_name_len = + strlen(item->profile->name) + strlen(".ignore") + 1; + char option_name[option_name_len]; + snprintf(option_name, option_name_len - 1, "%s.ignore", + item->profile->name); + struct t_weelist_item *ignore_item; + for (ignore_item = weechat_list_get(item->profile->ignores, 0); + ignore_item; ignore_item = weechat_list_next(ignore_item)) + { + if (!weechat_config_write_line(config_file, option_name, + weechat_list_string(ignore_item))) + return WEECHAT_CONFIG_WRITE_ERROR; + } + } + return WEECHAT_CONFIG_WRITE_OK; +} + /** * Create a new option for a profile. Returns NULL if an error occurs. */ @@ -350,6 +426,12 @@ twc_config_init() twc_config_file, "profile_default", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + twc_config_section_ignore = weechat_config_new_section( + twc_config_file, "ignore", 0, 0, twc_config_ignore_read_callback, NULL, + NULL, twc_config_ignore_write_callback, NULL, NULL, + twc_config_ignore_write_callback, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL); + for (int i = 0; i < TWC_PROFILE_NUM_OPTIONS; ++i) { twc_config_profile_default[i] = @@ -374,6 +456,11 @@ twc_config_init() NULL, 2, TOX_PUBLIC_KEY_SIZE * 2, "8", NULL, 0, twc_config_check_value_callback, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + twc_config_show_id = weechat_config_new_option( + twc_config_file, twc_config_section_look, "show_id", "boolean", + "show short Tox IDs in message logs and presence logs of group chats", + NULL, 0, 0, "on", NULL, 0, twc_config_check_value_callback, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); } /** diff --git a/src/twc-config.h b/src/twc-config.h index 80d9418..4095d8c 100644 --- a/src/twc-config.h +++ b/src/twc-config.h @@ -24,6 +24,7 @@ struct t_twc_profile; extern struct t_config_option *twc_config_friend_request_message; extern struct t_config_option *twc_config_short_id_size; +extern struct t_config_option *twc_config_show_id; enum t_twc_proxy { diff --git a/src/twc-profile.c b/src/twc-profile.c index 7936794..f460033 100644 --- a/src/twc-profile.c +++ b/src/twc-profile.c @@ -166,6 +166,7 @@ twc_profile_new(const char *name) profile->tox_online = false; profile->chats = twc_list_new(); + profile->ignores = weechat_list_new(); profile->friend_requests = twc_list_new(); profile->group_chat_invites = twc_list_new(); profile->message_queues = weechat_hashtable_new( @@ -247,10 +248,10 @@ twc_tox_new_print_error(struct t_twc_profile *profile, weechat_prefix("error"), options->proxy_host); break; case TOX_ERR_NEW_PROXY_BAD_PORT: - weechat_printf(profile->buffer, - "%scould not load Tox (invalid proxy port: \"%" - PRIu16 "\")", - weechat_prefix("error"), options->proxy_port); + weechat_printf( + profile->buffer, + "%scould not load Tox (invalid proxy port: \"%" PRIu16 "\")", + weechat_prefix("error"), options->proxy_port); break; case TOX_ERR_NEW_PROXY_NOT_FOUND: weechat_printf( @@ -698,6 +699,8 @@ twc_profile_free(struct t_twc_profile *profile) /* free things */ twc_chat_free_list(profile->chats); + weechat_list_remove_all(profile->ignores); + weechat_list_free(profile->ignores); twc_friend_request_free_list(profile->friend_requests); twc_group_chat_invite_free_list(profile->group_chat_invites); twc_tfer_free(profile->tfer); diff --git a/src/twc-profile.h b/src/twc-profile.h index eca37f5..baeb1d2 100644 --- a/src/twc-profile.h +++ b/src/twc-profile.h @@ -59,6 +59,7 @@ struct t_twc_profile struct t_hook *tox_do_timer; struct t_twc_list *chats; + struct t_weelist *ignores; struct t_twc_list *friend_requests; struct t_twc_list *group_chat_invites; struct t_hashtable *message_queues; diff --git a/src/twc-tox-callbacks.c b/src/twc-tox-callbacks.c index 6117fb6..b1af588 100644 --- a/src/twc-tox-callbacks.c +++ b/src/twc-tox-callbacks.c @@ -28,6 +28,7 @@ #endif /* TOXAV_ENABLED */ #include "twc-chat.h" +#include "twc-config.h" #include "twc-friend-request.h" #include "twc-group-invite.h" #include "twc-message-queue.h" @@ -407,11 +408,19 @@ twc_handle_group_message(Tox *tox, int32_t group_number, int32_t peer_number, bool rc; struct t_twc_profile *profile = data; + char *short_id = + twc_get_peer_id_short(profile->tox, group_number, peer_number); + if (twc_is_id_ignored(profile, short_id)) + { + free(short_id); + return; + } struct t_twc_chat *chat = twc_chat_search_group(profile, group_number, true); char *myname = twc_get_self_name_nt(profile->tox); char *name = twc_get_peer_name_nt(profile->tox, group_number, peer_number); + char *full_name = twc_get_peer_name_prefixed(short_id, name); char *tags = "notify_message"; char *message_nt = twc_null_terminate(message, length); @@ -425,10 +434,14 @@ twc_handle_group_message(Tox *tox, int32_t group_number, int32_t peer_number, if (weechat_string_has_highlight(message_nt, myname)) tags = "notify_highlight"; - twc_chat_print_message(chat, tags, nick_color, name, message_nt, - message_type); + twc_chat_print_message( + chat, tags, nick_color, + weechat_config_boolean(twc_config_show_id) ? full_name : name, + message_nt, message_type); free(name); + free(short_id); + free(full_name); free(myname); free(message_nt); } @@ -456,58 +469,95 @@ twc_group_peer_list_changed_callback(Tox *tox, uint32_t group_number, struct t_weelist *new_nicks; struct t_weelist_item *n; + struct t_weelist *new_ids; + struct t_weelist_item *id; npeers = tox_conference_peer_count(profile->tox, group_number, &err); if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) { new_nicks = weechat_list_new(); + new_ids = weechat_list_new(); for (i = 0; i < npeers; i++) { char *name = twc_get_peer_name_nt(profile->tox, group_number, i); + char *id = twc_get_peer_id_short(profile->tox, group_number, i); weechat_list_add(new_nicks, name, WEECHAT_LIST_POS_END, NULL); + weechat_list_add(new_ids, id, WEECHAT_LIST_POS_END, NULL); free(name); + free(id); } } else return; + bool changed = false; + /* searching for exits */ n = weechat_list_get(chat->nicks, 0); + id = weechat_list_get(chat->ids, 0); - while (n) + while (id && n) { + const char *short_id = weechat_list_string(id); const char *name = weechat_list_string(n); - if (!weechat_list_search(new_nicks, name)) + if (!weechat_list_search(new_ids, short_id)) { - weechat_printf(chat->buffer, "%s%s just left the group chat", - weechat_prefix("quit"), name); - nick = weechat_nicklist_search_nick(chat->buffer, - chat->nicklist_group, name); + char *full_name = twc_get_peer_name_prefixed(short_id, name); + nick = weechat_nicklist_search_nick( + chat->buffer, chat->nicklist_group, full_name); weechat_nicklist_remove_nick(chat->buffer, nick); + weechat_printf( + chat->buffer, "%s%s just left the group chat", + weechat_prefix("quit"), + weechat_config_boolean(twc_config_show_id) ? full_name : name); + changed = true; + free(full_name); } n = weechat_list_next(n); + id = weechat_list_next(id); } /* searching for joins */ n = weechat_list_get(new_nicks, 0); + id = weechat_list_get(new_ids, 0); - while (n) + while (id && n) { + const char *short_id = weechat_list_string(id); const char *name = weechat_list_string(n); - if (!weechat_list_search(chat->nicks, name)) + if (!weechat_list_search(chat->ids, short_id)) { - weechat_printf(chat->buffer, "%s%s just joined the group chat", - weechat_prefix("join"), name); - weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, name, - NULL, NULL, NULL, 1); + char *full_name = twc_get_peer_name_prefixed(short_id, name); + weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, + full_name, NULL, NULL, NULL, 1); + nick = weechat_nicklist_search_nick( + chat->buffer, chat->nicklist_group, full_name); + struct t_weelist_item *ignored = + twc_is_id_ignored(profile, short_id); + twc_chat_update_prefix_by_nick(chat->buffer, nick, + ignored ? "-" : " ", + ignored ? "yellow" : "default"); + weechat_printf( + chat->buffer, "%s%s just joined the group chat", + weechat_prefix("join"), + weechat_config_boolean(twc_config_show_id) ? full_name : name); + changed = true; + free(full_name); } n = weechat_list_next(n); + id = weechat_list_next(id); } - weechat_list_remove_all(chat->nicks); - weechat_list_free(chat->nicks); - chat->nicks = new_nicks; + if (changed) + { + weechat_list_remove_all(chat->nicks); + weechat_list_free(chat->nicks); + weechat_list_remove_all(chat->ids); + weechat_list_free(chat->ids); + chat->nicks = new_nicks; + chat->ids = new_ids; + } } void @@ -523,10 +573,13 @@ twc_group_peer_name_callback(Tox *tox, uint32_t group_number, struct t_gui_nick *nick = NULL; const char *prev_name; char *name; + const char *short_id; + char *prev_full_name; + char *full_name; bool rc; TOX_ERR_CONFERENCE_PEER_QUERY err = TOX_ERR_CONFERENCE_PEER_QUERY_OK; - struct t_weelist_item *n; + struct t_weelist_item *n, *id; npeers = tox_conference_peer_count(profile->tox, group_number, &err); @@ -550,27 +603,36 @@ twc_group_peer_name_callback(Tox *tox, uint32_t group_number, twc_group_peer_list_changed_callback(tox, group_number, data); return; } - + id = weechat_list_get(chat->ids, peer_number); + short_id = weechat_list_string(id); prev_name = weechat_list_string(n); + prev_full_name = twc_get_peer_name_prefixed(short_id, prev_name); + name = twc_null_terminate(pname, pname_len); + full_name = twc_get_peer_name_prefixed(short_id, name); nick = weechat_nicklist_search_nick(chat->buffer, chat->nicklist_group, - prev_name); - + prev_full_name); weechat_nicklist_remove_nick(chat->buffer, nick); err = TOX_ERR_CONFERENCE_PEER_QUERY_OK; rc = tox_conference_peer_number_is_ours(tox, group_number, peer_number, &err); + bool show_id = weechat_config_boolean(twc_config_show_id); if ((err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) && (!rc)) - weechat_printf(chat->buffer, "%s%s is now known as %s", - weechat_prefix("network"), prev_name, name); - + weechat_printf( + chat->buffer, "%s%s is now known as %s", weechat_prefix("network"), + show_id ? prev_full_name : prev_name, show_id ? full_name : name); weechat_list_set(n, name); - - weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, name, NULL, - NULL, NULL, 1); - + weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, full_name, + NULL, NULL, NULL, 1); + struct t_weelist_item *ignored = twc_is_id_ignored(profile, short_id); + nick = weechat_nicklist_search_nick(chat->buffer, chat->nicklist_group, + full_name); + twc_chat_update_prefix_by_nick(chat->buffer, nick, ignored ? "-" : " ", + ignored ? "yellow" : "default"); + free(prev_full_name); + free(full_name); free(name); } diff --git a/src/twc-utils.c b/src/twc-utils.c index 8405dfd..97d4293 100644 --- a/src/twc-utils.c +++ b/src/twc-utils.c @@ -178,7 +178,124 @@ twc_get_friend_id_short(Tox *tox, int32_t friend_number) } /** - * Reverse the bytes of a 32-bit integer. + * Return a group peer's Tox ID in short form. Return value must be freed. + */ +char * +twc_get_peer_id_short(Tox *tox, uint32_t conference_number, + uint32_t peer_number) +{ + uint8_t peer_id[TOX_PUBLIC_KEY_SIZE]; + TOX_ERR_CONFERENCE_PEER_QUERY err; + size_t short_id_length = weechat_config_integer(twc_config_short_id_size); + short_id_length = + short_id_length > 4 ? short_id_length : 4; /* Let's use a sane value */ + char *hex_address = malloc(short_id_length + 1); + + tox_conference_peer_get_public_key(tox, conference_number, peer_number, + peer_id, &err); + if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) + memset(peer_id, 0, TOX_PUBLIC_KEY_SIZE); + + twc_bin2hex(peer_id, short_id_length / 2, hex_address); + return hex_address; +} + +/** + * Prefix a nickname with Tox ID in short form. Return value must be freed. + */ +char * +twc_get_peer_name_prefixed(const char *id, const char *name) +{ + if (!name) + name = "Tox User"; + size_t full_length = strlen(id) + strlen(name) + 4; + char *full_name = malloc(full_length); + snprintf(full_name, full_length, "[%s] %s", id, name); + return full_name; +} + +/** + * Return amount of times a certain nickname repeats in a t_weelist list. + */ +size_t +twc_get_peer_name_count(struct t_weelist *list, const char *name) +{ + size_t count = 0; + struct t_weelist_item *item = weechat_list_get(list, 0); + for (item = weechat_list_get(list, 0); item; item = weechat_list_next(item)) + { + if (!strcmp(weechat_list_string(item), name)) + count++; + } + return count; +} + +/** + * Return t_weelist* to a list of strings which start with a certain string, + * NULL otherwise if there's no such strings. Must be properly freed after + * usage. + */ +struct t_weelist * +twc_starts_with(struct t_weelist *list, const char *search, + struct t_weelist *result) +{ + size_t length = strlen(search); + weechat_list_remove_all(result); + if (!search || !length) + return result; + struct t_weelist_item *item = weechat_list_get(list, 0); + while (item) + { + const char *string = weechat_list_string(item); + if (strlen(string) >= length && !strncmp(search, string, length)) + weechat_list_add(result, string, WEECHAT_LIST_POS_SORT, NULL); + item = weechat_list_next(item); + } + return result; +} + +/** + * Return next completion string regarding of a previous one. + */ + +const char * +twc_get_next_completion(struct t_weelist *completion_list, + const char *prev_comp) +{ + if (!weechat_list_size(completion_list)) + return NULL; + const char *comp = + weechat_list_string(weechat_list_get(completion_list, 0)); + if (prev_comp) + { + struct t_weelist_item *item = + weechat_list_search(completion_list, prev_comp); + if (item && (item = weechat_list_next(item))) + comp = weechat_list_string(item); + } + return comp; +} + +/** + * Checks if an ID is ignored. Returns the item from the ignore list if so, NULL + * otherwise. + */ +struct t_weelist_item * +twc_is_id_ignored(struct t_twc_profile *profile, const char *short_id) +{ + struct t_weelist_item *ignore_item; + for (ignore_item = weechat_list_get(profile->ignores, 0); ignore_item; + ignore_item = weechat_list_next(ignore_item)) + { + if (!weechat_strncasecmp(short_id, weechat_list_string(ignore_item), + strlen(short_id))) + return ignore_item; + } + return NULL; +} + +/** + * reverse the bytes of a 32-bit integer. */ uint32_t twc_uint32_reverse_bytes(uint32_t num) diff --git a/src/twc-utils.h b/src/twc-utils.h index b1d2f3d..18baa0e 100644 --- a/src/twc-utils.h +++ b/src/twc-utils.h @@ -21,10 +21,11 @@ #define TOX_WEECHAT_UTILS_H #include - #include #include +#include "twc-profile.h" + void twc_hex2bin(const char *hex, size_t size, uint8_t *out); @@ -49,6 +50,34 @@ twc_get_self_name_nt(Tox *tox); char * twc_get_friend_id_short(Tox *tox, int32_t friend_number); +char * +twc_get_peer_id_short(Tox *tox, uint32_t conference_number, + uint32_t peer_number); + +char * +twc_get_peer_name_prefixed(const char *id, const char *name); + +char * +twc_get_peer_name_prefixed_and_aligned(const char *id, const char *name, + size_t max); + +size_t +twc_get_max_string_length(struct t_weelist *list); + +size_t +twc_get_peer_name_count(struct t_weelist *list, const char *name); + +struct t_weelist * +twc_starts_with(struct t_weelist *list, const char *search, + struct t_weelist *result); + +const char * +twc_get_next_completion(struct t_weelist *completion_list, + const char *prev_comp); + +struct t_weelist_item * +twc_is_id_ignored(struct t_twc_profile *profile, const char *short_id); + uint32_t twc_uint32_reverse_bytes(uint32_t num);