diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 687fd203c..1078dcfd6 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -21,7 +21,7 @@ New features:: * core: add variable `${highlight}` in option weechat.look.buffer_time_format (issue #2079) * core: convert option weechat.look.hotlist_sort to a list of fields (issue #2097) * core: rename variables with creation time in hdata "hotlist": "creation_time.tv_sec" to "time" and "creation_time.tv_usec" to "time_usec" - * core: add unique identifier "id" in buffer (issue #2081) + * core: add unique identifier "id" in buffer and nicklist (group and nick) (issue #2081) * core: add option `malloc_trim` in command `/sys` * core: add support of SGR mouse events (issue #2082) * core: reintroduce help on the variables and operators in `/help eval` (issue #2005) diff --git a/doc/en/weechat_dev.en.adoc b/doc/en/weechat_dev.en.adoc index b96096e09..86c5561cc 100644 --- a/doc/en/weechat_dev.en.adoc +++ b/doc/en/weechat_dev.en.adoc @@ -448,6 +448,7 @@ WeeChat "core" is located in following directories: |          test-gui-key.cpp | Tests: keys. |          test-gui-line.cpp | Tests: lines. |          test-gui-nick.cpp | Tests: nicks. +|          test-gui-nicklist.cpp | Tests: nicklist functions. |          curses/ | Root of unit tests for Curses interface. |             test-gui-curses-mouse.cpp | Tests: mouse (Curses interface). |       plugins/ | Root of unit tests for plugins. diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index a5cdf5e84..78405efdb 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -14699,6 +14699,7 @@ Arguments: ** _short_name_: short name of buffer (note: used for display only and can be changed by user, this must not be used to find name of buffer, use instead _name_, _full_name_ or local variable _channel_) ** _type_: type of buffer: "formatted" or "free" _(WeeChat ≥ 4.2.0)_ ** _title_: title of buffer +** _nicklist_last_id_assigned_: last unique identifier used in this buffer for a group or nick _(WeeChat ≥ 4.3.0)_ ** _input_: input text ** _text_search_input_: input saved before text search ** _highlight_words_: list of words to highlight @@ -15870,6 +15871,7 @@ Arguments: * _buffer_: buffer pointer * _group_: group pointer * _property_: property name: +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: name of group ** _color_: group color in nicklist @@ -16072,6 +16074,7 @@ Arguments: * _buffer_: buffer pointer * _nick_: nick pointer * _property_: property name: +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: name of nick ** _color_: nick color in nicklist ** _prefix_: prefix of nick diff --git a/doc/fr/weechat_dev.fr.adoc b/doc/fr/weechat_dev.fr.adoc index 9ab4fce13..51f8f9415 100644 --- a/doc/fr/weechat_dev.fr.adoc +++ b/doc/fr/weechat_dev.fr.adoc @@ -450,6 +450,7 @@ Le cœur de WeeChat est situé dans les répertoires suivants : |          test-gui-key.cpp | Tests : touches. |          test-gui-line.cpp | Tests : lignes. |          test-gui-nick.cpp | Tests : pseudos. +|          test-gui-nicklist.cpp | Tests : fonctions de liste de pseudos. |          curses/ | Racine des tests unitaires pour l'interface Curses. |             test-gui-curses-mouse.cpp | Tests : souris (interface Curses). |       plugins/ | Racine des tests unitaires pour les extensions. diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index ea4acd4e5..ec62d7d9e 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -15016,6 +15016,7 @@ Paramètres : ** _short_name_ : nom court du tampon (note : utilisé pour l'affichage seulement et peut être changé par l'utilisateur, il ne doit pas être utilisé pour trouver le nom du tampon, utilisez à la place _name_, _full_name_ ou bien la variable locale _channel_) ** _type_ : type de tampon : "formatted" (formaté) ou "free" (contenu libre) _(WeeChat ≥ 4.2.0)_ ** _title_ : titre du tampon +** _nicklist_last_id_assigned_ : dernier identifiant unique utilisé dans ce tampon pour un groupe ou un pseudo _(WeeChat ≥ 4.3.0)_ ** _input_ : texte saisi ** _text_search_input_ : texte saisi sauvegardé avant la recherche de texte ** _highlight_words_ : liste des mots pour le highlight @@ -16213,6 +16214,7 @@ Paramètres : * _buffer_ : pointeur vers le tampon * _group_ : pointeur vers le groupe * _property_ : nom de la propriété : +** _id_ : identifiant unique _(WeeChat ≥ 4.3.0)_ ** _name_ : nom du groupe ** _color_ : couleur du groupe dans la liste des pseudos @@ -16416,6 +16418,7 @@ Paramètres : * _buffer_ : pointeur vers le tampon * _nick_ : pointeur vers le pseudo * _property_ : nom de la propriété : +** _id_ : identifiant unique _(WeeChat ≥ 4.3.0)_ ** _name_ : nom du pseudo ** _color_ : couleur du pseudo dans la liste des pseudos ** _prefix_ : préfixe du pseudo diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index a3fcab585..f3d001cac 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -15398,6 +15398,8 @@ Argomenti: // TRANSLATION MISSING ** _type_: type of buffer: "formatted" or "free" _(WeeChat ≥ 4.2.0)_ ** _title_: titolo del buffer +// TRANSLATION MISSING +** _nicklist_last_id_assigned_: last unique identifier used in this buffer for a group or nick _(WeeChat ≥ 4.3.0)_ ** _input_: testo in ingresso ** _text_search_input_: input salvato prima della ricerca nel testo ** _highlight_words_: elenco di parole da evidenziare @@ -16620,6 +16622,8 @@ Argomenti: * _buffer_: puntatore al buffer * _group_: puntatore al gruppo * _property_: nome della proprietà: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: nome del gruppo ** _color_: colore del gruppo nella lista nick @@ -16826,6 +16830,8 @@ Argomenti: * _buffer_: puntatore al buffer * _nick_: puntatore al nick * _property_: nome della proprietà: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: nome del nick ** _color_: colore del nick nella lista nick ** _prefix_: prefisso del nick diff --git a/doc/ja/weechat_dev.ja.adoc b/doc/ja/weechat_dev.ja.adoc index bbf6791cc..6c054b398 100644 --- a/doc/ja/weechat_dev.ja.adoc +++ b/doc/ja/weechat_dev.ja.adoc @@ -508,6 +508,8 @@ WeeChat "core" は以下のディレクトリに配置されています: // TRANSLATION MISSING |          test-gui-nick.cpp | テスト: nicks // TRANSLATION MISSING +|          test-gui-nicklist.cpp | Tests: nicklist functions. +// TRANSLATION MISSING |          curses/ | Root of unit tests for Curses interface. // TRANSLATION MISSING |             test-gui-curses-mouse.cpp | Tests: mouse (Curses interface). diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index a38b6fd95..6b8ea1577 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -14933,6 +14933,8 @@ const char *weechat_buffer_get_string (struct t_gui_buffer *buffer, // TRANSLATION MISSING ** _type_: type of buffer: "formatted" or "free" _(WeeChat ≥ 4.2.0)_ ** _title_: バッファのタイトル +// TRANSLATION MISSING +** _nicklist_last_id_assigned_: last unique identifier used in this buffer for a group or nick _(WeeChat ≥ 4.3.0)_ ** _input_: 入力テキスト ** _text_search_input_: テキスト検索前に保存した入力テキスト ** _highlight_words_: ハイライトする単語のリスト @@ -16112,6 +16114,8 @@ const char *weechat_nicklist_group_get_string (struct t_gui_buffer *buffer, * _buffer_: バッファへのポインタ * _group_: グループへのポインタ * _property_: プロパティ名: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: グループの名前 ** _color_: ニックネームリストのグループ色 @@ -16315,6 +16319,8 @@ const char *weechat_nicklist_nick_get_string (struct t_gui_buffer *buffer, * _buffer_: バッファへのプロパティ * _nick_: ニックネームへのポインタ * _property_: プロパティ名: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: ニックネームの名前 ** _color_: ニックネームリスト内でのニックネームの色 ** _prefix_: ニックネームのプレフィックス diff --git a/doc/sr/weechat_dev.sr.adoc b/doc/sr/weechat_dev.sr.adoc index 369eb7cdb..fd0df161b 100644 --- a/doc/sr/weechat_dev.sr.adoc +++ b/doc/sr/weechat_dev.sr.adoc @@ -456,6 +456,8 @@ WeeChat „језгро” се налази у следећим директо |          test-gui-line.cpp | Тестови: линије. |          test-gui-nick.cpp | Тестови: надимци. // TRANSLATION MISSING +|          test-gui-nicklist.cpp | Tests: nicklist functions. +// TRANSLATION MISSING |          curses/ | Root of unit tests for Curses interface. // TRANSLATION MISSING |             test-gui-curses-mouse.cpp | Tests: mouse (Curses interface). diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc index 456f478a7..19955a3e2 100644 --- a/doc/sr/weechat_plugin_api.sr.adoc +++ b/doc/sr/weechat_plugin_api.sr.adoc @@ -14292,6 +14292,8 @@ const char *weechat_buffer_get_string (struct t_gui_buffer *buffer, ** _short_name_: кратко име бафера (напомена: користи се само за приказ и корисник може да га промени, ово не сме да се употребљава за проналажење имена бафера, уместо њега употребите _name_, _full_name_ или локалну променљиву _channel_) ** _type_: тип бафера: „formatted” или „free” _(WeeChat ≥ 4.2.0)_ ** _title_: наслов бафера +// TRANSLATION MISSING +** _nicklist_last_id_assigned_: last unique identifier used in this buffer for a group or nick _(WeeChat ≥ 4.3.0)_ ** _input_: текст уноса ** _text_search_input_: сачувани унос пре претраге текста ** _highlight_words_: листа речи које се истичу @@ -15450,6 +15452,8 @@ const char *weechat_nicklist_group_get_string (struct t_gui_buffer *buffer, * _buffer_: показивач на бафер * _group_: показивач на групу * _property_: име особине: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: име групе ** _color_: боја групе у листи надимака @@ -15652,6 +15656,8 @@ const char *weechat_nicklist_nick_get_string (struct t_gui_buffer *buffer, * _buffer_: показивач на бафер * _nick_: показивач на надимак * _property_: име особине: +// TRANSLATION MISSING +** _id_: unique identifier _(WeeChat ≥ 4.3.0)_ ** _name_: име надимка ** _color_: боја надимка у листи надимака ** _prefix_: префикс надимка diff --git a/src/core/core-upgrade.c b/src/core/core-upgrade.c index b5c6f2ca7..ed03302dc 100644 --- a/src/core/core-upgrade.c +++ b/src/core/core-upgrade.c @@ -711,7 +711,9 @@ void upgrade_weechat_read_nicklist (struct t_infolist *infolist) { struct t_gui_nick_group *ptr_group; - const char *type, *name, *group_name; + const char *type, *name, *group_name, *ptr_id; + char *error; + long long id; if (!upgrade_current_buffer) return; @@ -719,42 +721,63 @@ upgrade_weechat_read_nicklist (struct t_infolist *infolist) upgrade_current_buffer->nicklist = 1; ptr_group = NULL; type = infolist_string (infolist, "type"); - if (type) + if (!type) + return; + + /* "id" is new in WeeChat 4.3.0 */ + id = -1; + if (infolist_search_var (infolist, "id")) { - if (strcmp (type, "group") == 0) + ptr_id = infolist_string (infolist, "id"); + if (ptr_id) { - name = infolist_string (infolist, "name"); - if (name && (strcmp (name, "root") != 0)) - { - group_name = infolist_string (infolist, "parent_name"); - if (group_name) - { - ptr_group = gui_nicklist_search_group ( - upgrade_current_buffer, NULL, group_name); - } - gui_nicklist_add_group (upgrade_current_buffer, - ptr_group, - name, - infolist_string (infolist, "color"), - infolist_integer (infolist, "visible")); - } + error = NULL; + id = strtoll (ptr_id, &error, 10); + if (!error || error[0]) + id = -1; } - else if (strcmp (type, "nick") == 0) + } + if (id < 0) + id = gui_nicklist_generate_id (upgrade_current_buffer); + + if (strcmp (type, "group") == 0) + { + name = infolist_string (infolist, "name"); + if (name && (strcmp (name, "root") != 0)) { - group_name = infolist_string (infolist, "group_name"); + group_name = infolist_string (infolist, "parent_name"); if (group_name) - ptr_group = gui_nicklist_search_group (upgrade_current_buffer, - NULL, - group_name); - gui_nicklist_add_nick (upgrade_current_buffer, - ptr_group, - infolist_string (infolist, "name"), - infolist_string (infolist, "color"), - infolist_string (infolist, "prefix"), - infolist_string (infolist, "prefix_color"), - infolist_integer (infolist, "visible")); + { + ptr_group = gui_nicklist_search_group ( + upgrade_current_buffer, NULL, group_name); + } + gui_nicklist_add_group_with_id ( + upgrade_current_buffer, + id, + ptr_group, + name, + infolist_string (infolist, "color"), + infolist_integer (infolist, "visible")); } } + else if (strcmp (type, "nick") == 0) + { + group_name = infolist_string (infolist, "group_name"); + if (group_name) + { + ptr_group = gui_nicklist_search_group ( + upgrade_current_buffer, NULL, group_name); + } + gui_nicklist_add_nick_with_id ( + upgrade_current_buffer, + id, + ptr_group, + infolist_string (infolist, "name"), + infolist_string (infolist, "color"), + infolist_string (infolist, "prefix"), + infolist_string (infolist, "prefix_color"), + infolist_integer (infolist, "visible")); + } } /* diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index 8941affea..d7edf0c90 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -110,9 +110,9 @@ char *gui_buffer_properties_get_integer[] = }; char *gui_buffer_properties_get_string[] = { "id", "plugin", "name", "full_name", "old_full_name", "short_name", "title", - "input", "text_search_input", "highlight_words", "highlight_disable_regex", - "highlight_regex", "highlight_tags_restrict", "highlight_tags", - "hotlist_max_level_nicks", + "nicklist_last_id_assigned", "input", "text_search_input", "highlight_words", + "highlight_disable_regex", "highlight_regex", "highlight_tags_restrict", + "highlight_tags", "hotlist_max_level_nicks", NULL }; char *gui_buffer_properties_get_pointer[] = @@ -888,10 +888,11 @@ gui_buffer_new_props_with_id (long long id, new_buffer->nicklist_groups_visible_count = 0; new_buffer->nicklist_nicks_count = 0; new_buffer->nicklist_nicks_visible_count = 0; + new_buffer->nicklist_last_id_assigned = -1; new_buffer->nickcmp_callback = NULL; new_buffer->nickcmp_callback_pointer = NULL; new_buffer->nickcmp_callback_data = NULL; - gui_nicklist_add_group (new_buffer, NULL, "root", NULL, 0); + gui_nicklist_add_group_with_id (new_buffer, 0, NULL, "root", NULL, 0); /* input */ new_buffer->input = 1; @@ -1539,6 +1540,12 @@ gui_buffer_get_string (struct t_gui_buffer *buffer, const char *property) return gui_buffer_type_string[buffer->type]; else if (strcmp (property, "title") == 0) return buffer->title; + else if (strcmp (property, "nicklist_last_id_assigned") == 0) + { + snprintf (str_value, sizeof (str_value), + "%lld", buffer->nicklist_last_id_assigned); + return str_value; + } else if (strcmp (property, "input") == 0) return buffer->input_buffer; else if (strcmp (property, "text_search_input") == 0) @@ -5188,6 +5195,7 @@ gui_buffer_hdata_buffer_cb (const void *pointer, void *data, HDATA_VAR(struct t_gui_buffer, nicklist_groups_visible_count, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, nicklist_nicks_count, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, nicklist_nicks_visible_count, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_buffer, nicklist_last_id_assigned, LONGLONG, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, nickcmp_callback, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, nickcmp_callback_pointer, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, nickcmp_callback_data, POINTER, 0, NULL, NULL); @@ -5407,6 +5415,9 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "nicklist_nicks_visible_count", buffer->nicklist_nicks_visible_count)) return 0; + snprintf (str_value, sizeof (str_value), "%lld", buffer->nicklist_last_id_assigned); + if (!infolist_new_var_string (ptr_item, "nicklist_last_id_assigned", str_value)) + return 0; if (!infolist_new_var_string (ptr_item, "title", buffer->title)) return 0; if (!infolist_new_var_integer (ptr_item, "input", buffer->input)) @@ -5643,6 +5654,7 @@ gui_buffer_print_log () log_printf (" nicklist_groups_vis_cnt : %d", ptr_buffer->nicklist_groups_visible_count); log_printf (" nicklist_nicks_count. . : %d", ptr_buffer->nicklist_nicks_count); log_printf (" nicklist_nicks_vis_cnt. : %d", ptr_buffer->nicklist_nicks_visible_count); + log_printf (" nicklist_last_id_assigned: %lld", ptr_buffer->nicklist_last_id_assigned); log_printf (" nickcmp_callback. . . . : %p", ptr_buffer->nickcmp_callback); log_printf (" nickcmp_callback_pointer: %p", ptr_buffer->nickcmp_callback_pointer); log_printf (" nickcmp_callback_data . : %p", ptr_buffer->nickcmp_callback_data); diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h index f3de457b6..09373e9be 100644 --- a/src/gui/gui-buffer.h +++ b/src/gui/gui-buffer.h @@ -169,6 +169,7 @@ struct t_gui_buffer int nicklist_groups_visible_count; /* number of groups displayed */ int nicklist_nicks_count; /* number of nicks */ int nicklist_nicks_visible_count; /* number of nicks displayed */ + long long nicklist_last_id_assigned; /* last id assigned for a grp/nick */ int (*nickcmp_callback)(const void *pointer, /* called to compare nicks */ void *data, /* (search in nicklist) */ struct t_gui_buffer *buffer, diff --git a/src/gui/gui-nicklist.c b/src/gui/gui-nicklist.c index 535c8c6b8..4d0443887 100644 --- a/src/gui/gui-nicklist.c +++ b/src/gui/gui-nicklist.c @@ -252,15 +252,45 @@ gui_nicklist_search_group (struct t_gui_buffer *buffer, } /* - * Adds a group to nicklist. + * Returns a new unique id for a group/nick. + * + * The id is the current time with microseconds precision. + * The same time (including microseconds) can be used only one time, so that + * all group/nick ids in a given buffer are guaranteed to be unique. + */ + +long long +gui_nicklist_generate_id (struct t_gui_buffer *buffer) +{ + struct timeval tv; + long long id; + + gettimeofday (&tv, NULL); + + id = ((long long)tv.tv_sec * 1000000LL) + (long long)(tv.tv_usec); + + /* + * ensure we never use the same id for two groups/nicks in the buffer + * and that the returned id is strictly greater than the last assigned one + * in the buffer + */ + if (id <= buffer->nicklist_last_id_assigned) + id = buffer->nicklist_last_id_assigned + 1; + + return id; +} + +/* + * Adds a group to nicklist with identifier (internal use). * * Returns pointer to new group, NULL if error. */ struct t_gui_nick_group * -gui_nicklist_add_group (struct t_gui_buffer *buffer, - struct t_gui_nick_group *parent_group, const char *name, - const char *color, int visible) +gui_nicklist_add_group_with_id (struct t_gui_buffer *buffer, long long id, + struct t_gui_nick_group *parent_group, + const char *name, const char *color, + int visible) { struct t_gui_nick_group *new_group; @@ -271,6 +301,9 @@ gui_nicklist_add_group (struct t_gui_buffer *buffer, if (!new_group) return NULL; + new_group->id = id; + if (new_group->id > buffer->nicklist_last_id_assigned) + buffer->nicklist_last_id_assigned = new_group->id; new_group->name = (char *)string_shared_get (name); new_group->color = (color) ? (char *)string_shared_get (color) : NULL; new_group->visible = visible; @@ -308,6 +341,29 @@ gui_nicklist_add_group (struct t_gui_buffer *buffer, return new_group; } +/* + * Adds a group to nicklist. + * + * Returns pointer to new group, NULL if error. + */ + +struct t_gui_nick_group * +gui_nicklist_add_group (struct t_gui_buffer *buffer, + struct t_gui_nick_group *parent_group, const char *name, + const char *color, int visible) +{ + if (!buffer) + return NULL; + + return gui_nicklist_add_group_with_id ( + buffer, + gui_nicklist_generate_id (buffer), + parent_group, + name, + color, + visible); +} + /* * Searches for position of a nick (to keep nicklist sorted). */ @@ -430,17 +486,17 @@ gui_nicklist_search_nick (struct t_gui_buffer *buffer, } /* - * Adds a nick to nicklist. + * Adds a nick to nicklist with identifier (internal use). * * Returns pointer to new nick, NULL if error. */ struct t_gui_nick * -gui_nicklist_add_nick (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *name, const char *color, - const char *prefix, const char *prefix_color, - int visible) +gui_nicklist_add_nick_with_id (struct t_gui_buffer *buffer, long long id, + struct t_gui_nick_group *group, + const char *name, const char *color, + const char *prefix, const char *prefix_color, + int visible) { struct t_gui_nick *new_nick; @@ -451,6 +507,9 @@ gui_nicklist_add_nick (struct t_gui_buffer *buffer, if (!new_nick) return NULL; + new_nick->id = id; + if (new_nick->id > buffer->nicklist_last_id_assigned) + buffer->nicklist_last_id_assigned = new_nick->id; new_nick->group = (group) ? group : buffer->nicklist_root; new_nick->name = (char *)string_shared_get (name); new_nick->color = (color) ? (char *)string_shared_get (color) : NULL; @@ -478,6 +537,33 @@ gui_nicklist_add_nick (struct t_gui_buffer *buffer, return new_nick; } +/* + * Adds a nick to nicklist. + * + * Returns pointer to new nick, NULL if error. + */ + +struct t_gui_nick * +gui_nicklist_add_nick (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *name, const char *color, + const char *prefix, const char *prefix_color, + int visible) +{ + if (!buffer) + return NULL; + + return gui_nicklist_add_nick_with_id ( + buffer, + gui_nicklist_generate_id (buffer), + group, + name, + color, + prefix, + prefix_color, + visible); +} + /* * Removes a nick from a group. */ @@ -1078,6 +1164,7 @@ gui_nicklist_hdata_nick_group_cb (const void *pointer, void *data, 0, 0, NULL, NULL); if (hdata) { + HDATA_VAR(struct t_gui_nick_group, id, LONGLONG, 0, NULL, NULL); HDATA_VAR(struct t_gui_nick_group, name, SHARED_STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_nick_group, color, SHARED_STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_nick_group, visible, INTEGER, 0, NULL, NULL); @@ -1111,6 +1198,7 @@ gui_nicklist_hdata_nick_cb (const void *pointer, void *data, 0, 0, NULL, NULL); if (hdata) { + HDATA_VAR(struct t_gui_nick, id, LONGLONG, 0, NULL, NULL); HDATA_VAR(struct t_gui_nick, group, POINTER, 0, NULL, "nick_group"); HDATA_VAR(struct t_gui_nick, name, SHARED_STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_nick, color, SHARED_STRING, 0, NULL, NULL); @@ -1136,6 +1224,7 @@ gui_nicklist_add_group_to_infolist (struct t_infolist *infolist, struct t_gui_nick_group *group) { struct t_infolist_item *ptr_item; + char str_value[64]; if (!infolist || !group) return 0; @@ -1144,6 +1233,9 @@ gui_nicklist_add_group_to_infolist (struct t_infolist *infolist, if (!ptr_item) return 0; + snprintf (str_value, sizeof (str_value), "%lld", group->id); + if (!infolist_new_var_string (ptr_item, "id", str_value)) + return 0; if (!infolist_new_var_string (ptr_item, "type", "group")) return 0; if (group->parent) @@ -1176,6 +1268,7 @@ gui_nicklist_add_nick_to_infolist (struct t_infolist *infolist, struct t_gui_nick *nick) { struct t_infolist_item *ptr_item; + char str_value[64]; if (!infolist || !nick) return 0; @@ -1184,6 +1277,9 @@ gui_nicklist_add_nick_to_infolist (struct t_infolist *infolist, if (!ptr_item) return 0; + snprintf (str_value, sizeof (str_value), "%lld", nick->id); + if (!infolist_new_var_string (ptr_item, "id", str_value)) + return 0; if (!infolist_new_var_string (ptr_item, "type", "nick")) return 0; if (nick->group) @@ -1273,6 +1369,10 @@ gui_nicklist_print_log (struct t_gui_nick_group *group, int indent) "%%-%ds=> group (addr:%%p)", (indent * 2) + 4); log_printf (format, " ", group); + snprintf (format, sizeof (format), + "%%-%dsid. . . . . : %%lld", + (indent * 2) + 6); + log_printf (format, " ", group->id); snprintf (format, sizeof (format), "%%-%dsname. . . . : '%%s'", (indent * 2) + 6); @@ -1336,6 +1436,10 @@ gui_nicklist_print_log (struct t_gui_nick_group *group, int indent) "%%-%dsgroup . . . . . : %%p", (indent * 2) + 6); log_printf (format, " ", ptr_nick->group); + snprintf (format, sizeof (format), + "%%-%dsid. . . . . . . : %%lld", + (indent * 2) + 6); + log_printf (format, " ", ptr_nick->id); snprintf (format, sizeof (format), "%%-%dsname. . . . . . : '%%s'", (indent * 2) + 6); diff --git a/src/gui/gui-nicklist.h b/src/gui/gui-nicklist.h index 752767e12..ce0d3c7e9 100644 --- a/src/gui/gui-nicklist.h +++ b/src/gui/gui-nicklist.h @@ -25,6 +25,7 @@ struct t_infolist; struct t_gui_nick_group { + long long id; /* unique id for group/nick in buffer*/ char *name; /* group name */ char *color; /* color for group in nicklist */ int visible; /* 1 if group is displayed */ @@ -40,6 +41,7 @@ struct t_gui_nick_group struct t_gui_nick { + long long id; /* unique id for group/nick in buffer*/ struct t_gui_nick_group *group; /* group which contains nick */ char *name; /* nick name */ char *color; /* color for nick in nicklist */ @@ -55,6 +57,13 @@ struct t_gui_nick extern struct t_gui_nick_group *gui_nicklist_search_group (struct t_gui_buffer *buffer, struct t_gui_nick_group *from_group, const char *name); +extern long long gui_nicklist_generate_id (struct t_gui_buffer *buffer); +extern struct t_gui_nick_group *gui_nicklist_add_group_with_id (struct t_gui_buffer *buffer, + long long id, + struct t_gui_nick_group *parent_group, + const char *name, + const char *color, + int visible); extern struct t_gui_nick_group *gui_nicklist_add_group (struct t_gui_buffer *buffer, struct t_gui_nick_group *parent_group, const char *name, @@ -63,6 +72,14 @@ extern struct t_gui_nick_group *gui_nicklist_add_group (struct t_gui_buffer *buf extern struct t_gui_nick *gui_nicklist_search_nick (struct t_gui_buffer *buffer, struct t_gui_nick_group *from_group, const char *name); +extern struct t_gui_nick *gui_nicklist_add_nick_with_id (struct t_gui_buffer *buffer, + long long id, + struct t_gui_nick_group *group, + const char *name, + const char *color, + const char *prefix, + const char *prefix_color, + int visible); extern struct t_gui_nick *gui_nicklist_add_nick (struct t_gui_buffer *buffer, struct t_gui_nick_group *group, const char *name, diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c index 1b45f17df..6382fad1c 100644 --- a/src/plugins/irc/irc-channel.c +++ b/src/plugins/irc/irc-channel.c @@ -33,12 +33,13 @@ #include "irc-color.h" #include "irc-command.h" #include "irc-config.h" +#include "irc-input.h" #include "irc-join.h" #include "irc-modelist.h" #include "irc-nick.h" #include "irc-protocol.h" #include "irc-server.h" -#include "irc-input.h" +#include "irc-upgrade.h" char *irc_channel_typing_state_string[IRC_CHANNEL_NUM_TYPING_STATES] = @@ -241,7 +242,8 @@ irc_channel_create_buffer (struct t_irc_server *server, if (ptr_buffer) { - weechat_nicklist_remove_all (ptr_buffer); + if (!irc_upgrading) + weechat_nicklist_remove_all (ptr_buffer); weechat_hashtable_map (buffer_props, &irc_channel_apply_props, ptr_buffer); } else diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c index f00bbc006..f3ee654d9 100644 --- a/src/plugins/irc/irc-nick.c +++ b/src/plugins/irc/irc-nick.c @@ -521,41 +521,25 @@ irc_nick_nicklist_set_color_all () } /* - * Adds a new nick in channel. + * Adds a new nick in channel, but do not update the buffer nicklist. + * This function is only called by the function `irc_nick_new` (below) and + * when restoring nicks after upgrade: in this case we want to just add nick + * in channel nicks without changing anything in the buffer nicklist, + * to preserve same identifiers). * * Returns pointer to new nick, NULL if error. */ struct t_irc_nick * -irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, - const char *nickname, const char *host, const char *prefixes, - int away, const char *account, const char *realname) +irc_nick_new_in_channel (struct t_irc_server *server, + struct t_irc_channel *channel, + const char *nickname, const char *host, + const char *prefixes, int away, const char *account, + const char *realname) { - struct t_irc_nick *new_nick, *ptr_nick; + struct t_irc_nick *new_nick; int length; - if (!nickname || !nickname[0]) - return NULL; - - if (!channel->nicks) - irc_channel_add_nicklist_groups (server, channel); - - /* nick already exists on this channel? */ - ptr_nick = irc_nick_search (server, channel, nickname); - if (ptr_nick) - { - /* remove old nick from nicklist */ - irc_nick_nicklist_remove (server, channel, ptr_nick); - - /* update nick prefixes */ - irc_nick_set_prefixes (server, ptr_nick, prefixes); - - /* add new nick in nicklist */ - irc_nick_nicklist_add (server, channel, ptr_nick); - - return ptr_nick; - } - /* alloc memory for new nick */ if ((new_nick = malloc (sizeof (*new_nick))) == NULL) return NULL; @@ -609,6 +593,49 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, channel->nick_completion_reset = 1; + return new_nick; +} + +/* + * Adds a new nick in channel. + * + * Returns pointer to new nick, NULL if error. + */ + +struct t_irc_nick * +irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, + const char *nickname, const char *host, const char *prefixes, + int away, const char *account, const char *realname) +{ + struct t_irc_nick *new_nick, *ptr_nick; + + if (!nickname || !nickname[0]) + return NULL; + + if (!channel->nicks) + irc_channel_add_nicklist_groups (server, channel); + + /* nick already exists on this channel? */ + ptr_nick = irc_nick_search (server, channel, nickname); + if (ptr_nick) + { + /* remove old nick from nicklist */ + irc_nick_nicklist_remove (server, channel, ptr_nick); + + /* update nick prefixes */ + irc_nick_set_prefixes (server, ptr_nick, prefixes); + + /* add new nick in nicklist */ + irc_nick_nicklist_add (server, channel, ptr_nick); + + return ptr_nick; + } + + new_nick = irc_nick_new_in_channel (server, channel, nickname, host, + prefixes, away, account, realname); + if (!new_nick) + return NULL; + /* add nick to buffer nicklist */ irc_nick_nicklist_add (server, channel, new_nick); diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h index 4c3d07a9e..3a1cc80e2 100644 --- a/src/plugins/irc/irc-nick.h +++ b/src/plugins/irc/irc-nick.h @@ -61,6 +61,14 @@ extern const char *irc_nick_get_prefix_color_name (struct t_irc_server *server, char prefix); extern void irc_nick_nicklist_set_prefix_color_all (); extern void irc_nick_nicklist_set_color_all (); +extern struct t_irc_nick *irc_nick_new_in_channel (struct t_irc_server *server, + struct t_irc_channel *channel, + const char *nickname, + const char *host, + const char *prefixes, + int away, + const char *account, + const char *realname); extern struct t_irc_nick *irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, const char *nickname, diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index 402a225e4..4a82af10f 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -42,6 +42,7 @@ struct t_irc_server *irc_upgrade_current_server = NULL; struct t_irc_channel *irc_upgrade_current_channel = NULL; struct t_irc_modelist *irc_upgrade_current_modelist = NULL; +int irc_upgrading = 0; /* @@ -795,14 +796,15 @@ irc_upgrade_read_cb (const void *pointer, void *data, case IRC_UPGRADE_TYPE_NICK: if (irc_upgrade_current_server && irc_upgrade_current_channel) { - ptr_nick = irc_nick_new (irc_upgrade_current_server, - irc_upgrade_current_channel, - weechat_infolist_string (infolist, "name"), - weechat_infolist_string (infolist, "host"), - weechat_infolist_string (infolist, "prefixes"), - weechat_infolist_integer (infolist, "away"), - weechat_infolist_string (infolist, "account"), - weechat_infolist_string (infolist, "realname")); + ptr_nick = irc_nick_new_in_channel ( + irc_upgrade_current_server, + irc_upgrade_current_channel, + weechat_infolist_string (infolist, "name"), + weechat_infolist_string (infolist, "host"), + weechat_infolist_string (infolist, "prefixes"), + weechat_infolist_integer (infolist, "away"), + weechat_infolist_string (infolist, "account"), + weechat_infolist_string (infolist, "realname")); if (ptr_nick) { /* @@ -1005,7 +1007,9 @@ irc_upgrade_load () if (!upgrade_file) return 0; + irc_upgrading = 1; rc = weechat_upgrade_read (upgrade_file); + irc_upgrading = 0; weechat_upgrade_close (upgrade_file); diff --git a/src/plugins/irc/irc-upgrade.h b/src/plugins/irc/irc-upgrade.h index c33e44d07..af2008f15 100644 --- a/src/plugins/irc/irc-upgrade.h +++ b/src/plugins/irc/irc-upgrade.h @@ -37,6 +37,8 @@ enum t_irc_upgrade_type IRC_UPGRADE_TYPE_MODELIST_ITEM, }; +extern int irc_upgrading; + extern int irc_upgrade_save (int force_disconnected_state); extern int irc_upgrade_load (); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cbce96b30..28e818fbb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -83,6 +83,7 @@ set(LIB_WEECHAT_UNIT_TESTS_CORE_SRC unit/gui/test-gui-key.cpp unit/gui/test-gui-line.cpp unit/gui/test-gui-nick.cpp + unit/gui/test-gui-nicklist.cpp unit/gui/curses/test-gui-curses-mouse.cpp scripts/test-scripts.cpp ) diff --git a/tests/tests.cpp b/tests/tests.cpp index 93703896a..f0e801323 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -94,6 +94,7 @@ IMPORT_TEST_GROUP(GuiInput); IMPORT_TEST_GROUP(GuiKey); IMPORT_TEST_GROUP(GuiLine); IMPORT_TEST_GROUP(GuiNick); +IMPORT_TEST_GROUP(GuiNicklist); /* GUI - Curses */ IMPORT_TEST_GROUP(GuiCursesMouse); /* scripts */ diff --git a/tests/unit/gui/test-gui-nicklist.cpp b/tests/unit/gui/test-gui-nicklist.cpp new file mode 100644 index 000000000..74e523816 --- /dev/null +++ b/tests/unit/gui/test-gui-nicklist.cpp @@ -0,0 +1,412 @@ +/* + * test-gui-nicklist.cpp - test nicklist functions + * + * Copyright (C) 2024 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include +#include "src/gui/gui-buffer.h" +#include "src/gui/gui-nicklist.h" +} + +#define TEST_BUFFER_NAME "test" + +TEST_GROUP(GuiNicklist) +{ +}; + +/* + * Tests functions: + * gui_nicklist_send_signal + */ + +TEST(GuiNicklist, SendSignal) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_send_hsignal + */ + +TEST(GuiNicklist, SendHsignal) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_find_pos_group + */ + +TEST(GuiNicklist, FindPosGroup) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_insert_group_sorted + */ + +TEST(GuiNicklist, InsertGroupSorted) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_search_group_internal + */ + +TEST(GuiNicklist, SearchGroupInternal) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_search_group + */ + +TEST(GuiNicklist, SearchGroup) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_generate_id + */ + +TEST(GuiNicklist, GenerateId) +{ + struct t_gui_buffer *buffer; + long long id; + + buffer = gui_buffer_new (NULL, TEST_BUFFER_NAME, + NULL, NULL, NULL, + NULL, NULL, NULL); + CHECK(buffer); + + CHECK(buffer->nicklist_last_id_assigned == 0); + + id = gui_nicklist_generate_id (buffer); + CHECK(id > buffer->nicklist_last_id_assigned); + id = gui_buffer_generate_id (); + CHECK(id > buffer->nicklist_last_id_assigned); + id = gui_buffer_generate_id (); + CHECK(id > buffer->nicklist_last_id_assigned); + + gui_buffer_close (buffer); +} + +/* + * Tests functions: + * gui_nicklist_add_group_with_id + */ + +TEST(GuiNicklist, AddGroupWithId) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_group + */ + +TEST(GuiNicklist, AddGroup) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_find_pos_nick + */ + +TEST(GuiNicklist, FindPosNick) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_insert_nick_sorted + */ + +TEST(GuiNicklist, InsertNickSorted) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_search_nick + */ + +TEST(GuiNicklist, SearchNick) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_nick_with_id + */ + +TEST(GuiNicklist, AddNickWithId) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_nick + */ + +TEST(GuiNicklist, AddNick) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_remove_nick + */ + +TEST(GuiNicklist, RemoveNick) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_remove_group + */ + +TEST(GuiNicklist, RemoveGroup) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_remove_all + */ + +TEST(GuiNicklist, RemoveAll) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_get_next_item + */ + +TEST(GuiNicklist, GetNextItem) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_get_group_start + */ + +TEST(GuiNicklist, GetGroupStart) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_get_max_length + */ + +TEST(GuiNicklist, GetMaxLength) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_compute_visible_count + */ + +TEST(GuiNicklist, ComputeVisibleCount) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_group_get_integer + */ + +TEST(GuiNicklist, GroupGetInteger) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_group_get_string + */ + +TEST(GuiNicklist, GroupGetString) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_group_get_pointer + */ + +TEST(GuiNicklist, GroupGetPointer) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_group_set + */ + +TEST(GuiNicklist, GroupSet) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_nick_get_integer + */ + +TEST(GuiNicklist, NickGetInteger) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_nick_get_string + */ + +TEST(GuiNicklist, NickGetString) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_nick_get_pointer + */ + +TEST(GuiNicklist, NickGetPointer) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_nick_set + */ + +TEST(GuiNicklist, NickSet) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_hdata_nick_group_cb + */ + +TEST(GuiNicklist, HdataNickGroupCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_hdata_nick_cb + */ + +TEST(GuiNicklist, HdataNickCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_group_to_infolist + */ + +TEST(GuiNicklist, AddGroupToInfolist) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_nick_to_infolist + */ + +TEST(GuiNicklist, AddNickToInfolist) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_add_to_infolist + */ + +TEST(GuiNicklist, AddToInfolist) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_print_log + */ + +TEST(GuiNicklist, PrintLog) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_nicklist_end + */ + +TEST(GuiNicklist, End) +{ + /* TODO: write tests */ +}