diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2009-06-10 12:40:05 +0200 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2009-06-10 12:40:05 +0200 |
commit | 8d58b81d83d9a5462f1b4aeb274a16a91ef213d1 (patch) | |
tree | 4bf0ef51ea845f54fa97012b1ebe9a85e24f1750 /src/gui | |
parent | fd31dbb97ec00ee49cec21c4731677c403c80564 (diff) | |
download | weechat-8d58b81d83d9a5462f1b4aeb274a16a91ef213d1.zip |
Add buffer merging feature, with /buffer merge/unmerge (task #7404)
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gui/Makefile.am | 2 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-chat.c | 161 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-color.c | 1 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-keyboard.c | 5 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-window.c | 28 | ||||
-rw-r--r-- | src/gui/gtk/gui-gtk-bar-window.c | 1 | ||||
-rw-r--r-- | src/gui/gtk/gui-gtk-chat.c | 7 | ||||
-rw-r--r-- | src/gui/gtk/gui-gtk-color.c | 1 | ||||
-rw-r--r-- | src/gui/gtk/gui-gtk-window.c | 22 | ||||
-rw-r--r-- | src/gui/gui-bar-item.c | 7 | ||||
-rw-r--r-- | src/gui/gui-buffer.c | 547 | ||||
-rw-r--r-- | src/gui/gui-buffer.h | 46 | ||||
-rw-r--r-- | src/gui/gui-chat.c | 663 | ||||
-rw-r--r-- | src/gui/gui-chat.h | 28 | ||||
-rw-r--r-- | src/gui/gui-color.h | 1 | ||||
-rw-r--r-- | src/gui/gui-filter.c | 34 | ||||
-rw-r--r-- | src/gui/gui-hotlist.c | 9 | ||||
-rw-r--r-- | src/gui/gui-input.c | 34 | ||||
-rw-r--r-- | src/gui/gui-input.h | 1 | ||||
-rw-r--r-- | src/gui/gui-line.c | 1068 | ||||
-rw-r--r-- | src/gui/gui-line.h | 106 | ||||
-rw-r--r-- | src/gui/gui-window.c | 72 |
23 files changed, 1848 insertions, 997 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index f71812928..a3c7342cd 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -28,6 +28,7 @@ gui-hotlist.c gui-hotlist.h gui-input.c gui-input.h gui-keyboard.c gui-keyboard.h gui-layout.c gui-layout.h +gui-line.c gui-line.h gui-main.h gui-nicklist.c gui-nicklist.h gui-window.c gui-window.h) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 011c543e6..92f3c4cef 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -44,6 +44,8 @@ lib_weechat_gui_common_a_SOURCES = gui-bar.c \ gui-keyboard.h \ gui-layout.c \ gui-layout.h \ + gui-line.c \ + gui-line.h \ gui-main.h \ gui-nicklist.c \ gui-nicklist.h \ diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c index d9c138cbc..4be162d9c 100644 --- a/src/gui/curses/gui-curses-chat.c +++ b/src/gui/curses/gui-curses-chat.c @@ -37,6 +37,7 @@ #include "../gui-chat.h" #include "../gui-color.h" #include "../gui-hotlist.h" +#include "../gui-line.h" #include "../gui-main.h" #include "../gui-window.h" #include "gui-curses.h" @@ -67,12 +68,12 @@ gui_chat_marker_for_line (struct t_gui_buffer *buffer, struct t_gui_line *line) struct t_gui_line *last_read_line; /* marker is not set for buffer? */ - if (!buffer->last_read_line) + if (!buffer->lines->last_read_line) return 0; - last_read_line = buffer->last_read_line; - if (!last_read_line->displayed) - last_read_line = gui_chat_get_prev_line_displayed (last_read_line); + last_read_line = buffer->lines->last_read_line; + if (!last_read_line->data->displayed) + last_read_line = gui_line_get_prev_displayed (last_read_line); if (!last_read_line) return 0; @@ -87,7 +88,7 @@ gui_chat_marker_for_line (struct t_gui_buffer *buffer, struct t_gui_line *line) if (last_read_line == line) return 1; - if (line->displayed) + if (line->data->displayed) break; line = line->next_line; @@ -440,7 +441,7 @@ gui_chat_display_word (struct t_gui_window *window, while (data && data[0]) { /* insert spaces for align text under time/nick */ - length_align = gui_chat_get_line_align (window->buffer, line, 0); + length_align = gui_line_get_align (window->buffer, line, 0); if ((length_align > 0) && (window->win_chat_cursor_x == 0) && (*lines_displayed > 0) && @@ -540,15 +541,17 @@ gui_chat_display_time_and_prefix (struct t_gui_window *window, int simulate) { char str_space[] = " ", str_plus[] = "+", *prefix_highlighted; - int i, length_allowed, num_spaces; + int i, length, length_allowed, num_spaces; + struct t_gui_lines *mixed_lines; /* display time */ - if (window->buffer->time_for_each_line && (line->str_time && line->str_time[0])) + if (window->buffer->time_for_each_line + && (line->data->str_time && line->data->str_time[0])) { if (!simulate) gui_window_reset_style (GUI_WINDOW_OBJECTS(window)->win_chat, GUI_COLOR_CHAT); - gui_chat_display_word (window, line, line->str_time, + gui_chat_display_word (window, line, line->data->str_time, NULL, 1, num_lines, count, lines_displayed, simulate); gui_chat_display_word (window, line, str_space, @@ -564,25 +567,73 @@ gui_chat_display_time_and_prefix (struct t_gui_window *window, NULL, 1, num_lines, count, lines_displayed, simulate); } + + /* display buffer name (if many buffers are merged) */ + mixed_lines = line->data->buffer->mixed_lines; + if (mixed_lines) + { + if (!simulate) + { + gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, + GUI_COLOR_CHAT_PREFIX_BUFFER); + } + + length = gui_chat_strlen_screen (line->data->buffer->short_name); + num_spaces = mixed_lines->buffer_max_length - length; + + if (CONFIG_INTEGER(config_look_prefix_buffer_align) == CONFIG_LOOK_PREFIX_BUFFER_ALIGN_RIGHT) + { + for (i = 0; i < num_spaces; i++) + { + gui_chat_display_word (window, line, str_space, + NULL, 1, num_lines, count, + lines_displayed, simulate); + } + } + + gui_chat_display_word (window, line, + line->data->buffer->short_name, + NULL, 1, num_lines, count, lines_displayed, + simulate); + + if ((CONFIG_INTEGER(config_look_prefix_buffer_align) == CONFIG_LOOK_PREFIX_BUFFER_ALIGN_LEFT) + || ((CONFIG_INTEGER(config_look_prefix_buffer_align) == CONFIG_LOOK_PREFIX_BUFFER_ALIGN_NONE) + && (CONFIG_INTEGER(config_look_prefix_align) != CONFIG_LOOK_PREFIX_ALIGN_NONE))) + { + for (i = 0; i < num_spaces; i++) + { + gui_chat_display_word (window, line, str_space, + NULL, 1, num_lines, count, lines_displayed, + simulate); + } + } + + gui_chat_display_word (window, line, str_space, + NULL, 1, num_lines, count, lines_displayed, + simulate); + } /* display prefix */ - if (line->prefix - && (line->prefix[0] + if (line->data->prefix + && (line->data->prefix[0] || (CONFIG_INTEGER(config_look_prefix_align) != CONFIG_LOOK_PREFIX_ALIGN_NONE))) { if (!simulate) - gui_window_reset_style (GUI_WINDOW_OBJECTS(window)->win_chat, GUI_COLOR_CHAT); + { + gui_window_reset_style (GUI_WINDOW_OBJECTS(window)->win_chat, + GUI_COLOR_CHAT); + } if (CONFIG_INTEGER(config_look_prefix_align_max) > 0) { length_allowed = - (window->buffer->prefix_max_length <= CONFIG_INTEGER(config_look_prefix_align_max)) ? - window->buffer->prefix_max_length : CONFIG_INTEGER(config_look_prefix_align_max); + (window->buffer->lines->prefix_max_length <= CONFIG_INTEGER(config_look_prefix_align_max)) ? + window->buffer->lines->prefix_max_length : CONFIG_INTEGER(config_look_prefix_align_max); } else - length_allowed = window->buffer->prefix_max_length; + length_allowed = window->buffer->lines->prefix_max_length; - num_spaces = length_allowed - line->prefix_length; + num_spaces = length_allowed - line->data->prefix_length; if (CONFIG_INTEGER(config_look_prefix_align) == CONFIG_LOOK_PREFIX_ALIGN_RIGHT) { @@ -595,9 +646,9 @@ gui_chat_display_time_and_prefix (struct t_gui_window *window, } prefix_highlighted = NULL; - if (line->highlight) + if (line->data->highlight) { - prefix_highlighted = gui_color_decode (line->prefix, NULL); + prefix_highlighted = gui_color_decode (line->data->prefix, NULL); if (!simulate) { gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, @@ -610,19 +661,19 @@ gui_chat_display_time_and_prefix (struct t_gui_window *window, && (num_spaces < 0)) { gui_chat_display_word (window, line, - (prefix_highlighted) ? prefix_highlighted : line->prefix, + (prefix_highlighted) ? prefix_highlighted : line->data->prefix, (prefix_highlighted) ? prefix_highlighted + gui_chat_string_real_pos (prefix_highlighted, length_allowed) : - line->prefix + gui_chat_string_real_pos (line->prefix, - length_allowed), + line->data->prefix + gui_chat_string_real_pos (line->data->prefix, + length_allowed), 1, num_lines, count, lines_displayed, simulate); } else { gui_chat_display_word (window, line, - (prefix_highlighted) ? prefix_highlighted : line->prefix, + (prefix_highlighted) ? prefix_highlighted : line->data->prefix, NULL, 1, num_lines, count, lines_displayed, simulate); } @@ -656,7 +707,7 @@ gui_chat_display_time_and_prefix (struct t_gui_window *window, } else { - if (window->buffer->prefix_max_length > 0) + if (window->buffer->lines->prefix_max_length > 0) { gui_chat_display_word (window, line, str_space, NULL, 1, num_lines, count, lines_displayed, @@ -728,8 +779,8 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, } /* calculate marker position (maybe not used for this line!) */ - if (window->buffer->time_for_each_line && line->str_time) - read_marker_x = x + gui_chat_strlen_screen (line->str_time); + if (window->buffer->time_for_each_line && line->data->str_time) + read_marker_x = x + gui_chat_strlen_screen (line->data->str_time); else read_marker_x = x; read_marker_y = y; @@ -746,14 +797,14 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, if (!simulate) gui_window_reset_style (GUI_WINDOW_OBJECTS(window)->win_chat, GUI_COLOR_CHAT); - if (!line->message || !line->message[0]) + if (!line->data->message || !line->data->message[0]) { gui_chat_display_new_line (window, num_lines, count, &lines_displayed, simulate); } else { - ptr_data = line->message; + ptr_data = line->data->message; while (ptr_data && ptr_data[0]) { gui_chat_get_word_info (window, @@ -767,7 +818,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, if (word_length > 0) { /* spaces + word too long for current line but ok for next line */ - line_align = gui_chat_get_line_align (window->buffer, line, 1); + line_align = gui_line_get_align (window->buffer, line, 1); if ((window->win_chat_cursor_x + word_length_with_spaces > gui_chat_get_real_width (window)) && (word_length <= gui_chat_get_real_width (window) - line_align)) { @@ -830,7 +881,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, } } - if (marker_line && gui_chat_get_next_line_displayed (line)) + if (marker_line && gui_line_get_next_displayed (line)) { gui_chat_display_horizontal_line (window, simulate); gui_chat_display_new_line (window, num_lines, count, @@ -847,7 +898,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, /* display marker if line is matching user search */ if (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) { - if (gui_chat_line_search (line, window->buffer->input_buffer, + if (gui_line_search_text (line, window->buffer->input_buffer, window->buffer->text_search_exact)) { gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, @@ -861,8 +912,8 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, { /* display read marker if needed */ if ((CONFIG_INTEGER(config_look_read_marker) == CONFIG_LOOK_READ_MARKER_CHAR) - && window->buffer->last_read_line - && (window->buffer->last_read_line == gui_chat_get_prev_line_displayed (line))) + && window->buffer->lines->last_read_line + && (window->buffer->lines->last_read_line == gui_line_get_prev_displayed (line))) { gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, GUI_COLOR_CHAT_READ_MARKER); @@ -896,7 +947,7 @@ gui_chat_display_line_y (struct t_gui_window *window, struct t_gui_line *line, window->win_chat_cursor_x); wclrtoeol (GUI_WINDOW_OBJECTS(window)->win_chat); - if (gui_chat_display_word_raw (window, line->message, + if (gui_chat_display_word_raw (window, line->data->message, window->win_chat_width, 1) < window->win_chat_width) { gui_window_clrtoeol_with_current_bg (GUI_WINDOW_OBJECTS(window)->win_chat); @@ -925,7 +976,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, /* if looking backward, start at last line of buffer */ if (backward) { - *line = gui_chat_get_last_line_displayed (window->buffer); + *line = gui_line_get_last_displayed (window->buffer); if (!(*line)) return; current_size = gui_chat_display_line (window, *line, 0, 1); @@ -936,7 +987,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, /* if looking forward, start at first line of buffer */ else { - *line = gui_chat_get_first_line_displayed (window->buffer); + *line = gui_line_get_first_displayed (window->buffer); if (!(*line)) return; *line_pos = 0; @@ -955,7 +1006,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, (*line_pos)--; else { - *line = gui_chat_get_prev_line_displayed (*line); + *line = gui_line_get_prev_displayed (*line); if (*line) { current_size = gui_chat_display_line (window, *line, 0, 1); @@ -973,7 +1024,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, (*line_pos)++; else { - *line = gui_chat_get_next_line_displayed (*line); + *line = gui_line_get_next_displayed (*line); if (*line) { current_size = gui_chat_display_line (window, *line, 0, 1); @@ -992,7 +1043,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, if (backward) { /* first line reached */ - *line = gui_chat_get_first_line_displayed (window->buffer); + *line = gui_line_get_first_displayed (window->buffer); *line_pos = 0; } else @@ -1020,7 +1071,7 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) { - if (ptr_win->buffer == buffer) + if (ptr_win->buffer->number == buffer->number) { if (erase) { @@ -1069,18 +1120,18 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) ptr_line, 0, 1) - line_pos, 0); - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + ptr_line = gui_line_get_next_displayed (ptr_line); ptr_win->first_line_displayed = 0; } else ptr_win->first_line_displayed = - (ptr_line == gui_chat_get_first_line_displayed (ptr_win->buffer)); + (ptr_line == gui_line_get_first_displayed (ptr_win->buffer)); /* display lines */ while (ptr_line && (ptr_win->win_chat_cursor_y <= ptr_win->win_chat_height - 1)) { count = gui_chat_display_line (ptr_win, ptr_line, 0, 0); - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + ptr_line = gui_line_get_next_displayed (ptr_line); } old_scroll = ptr_win->scroll; @@ -1092,13 +1143,13 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) /* if so, disable scroll indicator */ if (!ptr_line && ptr_win->scroll) { - if ((count == gui_chat_display_line (ptr_win, gui_chat_get_last_line_displayed (ptr_win->buffer), 0, 1)) + if ((count == gui_chat_display_line (ptr_win, gui_line_get_last_displayed (ptr_win->buffer), 0, 1)) || (count == ptr_win->win_chat_height)) ptr_win->scroll = 0; } if (!ptr_win->scroll - && (ptr_win->start_line == gui_chat_get_first_line_displayed (ptr_win->buffer))) + && (ptr_win->start_line == gui_line_get_first_displayed (ptr_win->buffer))) { ptr_win->start_line = NULL; ptr_win->start_line_pos = 0; @@ -1110,7 +1161,7 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) /* count number of lines after last line displayed */ while (ptr_line) { - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + ptr_line = gui_line_get_next_displayed (ptr_line); if (ptr_line) ptr_win->scroll_lines_after++; } @@ -1144,23 +1195,23 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) case GUI_BUFFER_TYPE_FREE: /* display at position of scrolling */ ptr_line = (ptr_win->start_line) ? - ptr_win->start_line : buffer->lines; + ptr_win->start_line : buffer->lines->first_line; if (ptr_line) { - if (!ptr_line->displayed) - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + if (!ptr_line->data->displayed) + ptr_line = gui_line_get_next_displayed (ptr_line); if (ptr_line) { - y_start = (ptr_win->start_line) ? ptr_line->y : 0; + y_start = (ptr_win->start_line) ? ptr_line->data->y : 0; y_end = y_start + ptr_win->win_chat_height - 1; - while (ptr_line && (ptr_line->y <= y_end)) + while (ptr_line && (ptr_line->data->y <= y_end)) { - if (ptr_line->refresh_needed || erase) + if (ptr_line->data->refresh_needed || erase) { gui_chat_display_line_y (ptr_win, ptr_line, - ptr_line->y - y_start); + ptr_line->data->y - y_start); } - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + ptr_line = gui_line_get_next_displayed (ptr_line); } } } @@ -1176,10 +1227,10 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase) if (buffer->type == GUI_BUFFER_TYPE_FREE) { - for (ptr_line = buffer->lines; ptr_line; + for (ptr_line = buffer->lines->first_line; ptr_line; ptr_line = ptr_line->next_line) { - ptr_line->refresh_needed = 0; + ptr_line->data->refresh_needed = 0; } } diff --git a/src/gui/curses/gui-curses-color.c b/src/gui/curses/gui-curses-color.c index 1403e5e69..914713c61 100644 --- a/src/gui/curses/gui-curses-color.c +++ b/src/gui/curses/gui-curses-color.c @@ -382,6 +382,7 @@ gui_color_init_weechat () gui_color_build (GUI_COLOR_CHAT_READ_MARKER, CONFIG_COLOR(config_color_chat_read_marker), CONFIG_COLOR(config_color_chat_read_marker_bg)); gui_color_build (GUI_COLOR_CHAT_TEXT_FOUND, CONFIG_COLOR(config_color_chat_text_found), CONFIG_COLOR(config_color_chat_text_found_bg)); gui_color_build (GUI_COLOR_CHAT_VALUE, CONFIG_COLOR(config_color_chat_value), CONFIG_COLOR(config_color_chat_bg)); + gui_color_build (GUI_COLOR_CHAT_PREFIX_BUFFER, CONFIG_COLOR(config_color_chat_prefix_buffer), CONFIG_COLOR(config_color_chat_bg)); } /* diff --git a/src/gui/curses/gui-curses-keyboard.c b/src/gui/curses/gui-curses-keyboard.c index e19365c49..d7d1e6a4e 100644 --- a/src/gui/curses/gui-curses-keyboard.c +++ b/src/gui/curses/gui-curses-keyboard.c @@ -86,6 +86,7 @@ gui_keyboard_default_bindings () gui_keyboard_default_bind (/* del */ "meta2-3~", "/input delete_next_char"); gui_keyboard_default_bind (/* ^D */ "ctrl-D", "/input delete_next_char"); gui_keyboard_default_bind (/* ^W */ "ctrl-W", "/input delete_previous_word"); + gui_keyboard_default_bind (/* ^X */ "ctrl-X", "/input switch_active_buffer"); gui_keyboard_default_bind (/* m-d */ "meta-d", "/input delete_next_word"); gui_keyboard_default_bind (/* ^K */ "ctrl-K", "/input delete_end_of_line"); gui_keyboard_default_bind (/* m-r */ "meta-r", "/input delete_line"); @@ -114,16 +115,14 @@ gui_keyboard_default_bindings () gui_keyboard_default_bind (/* ^down */ "meta-Ob", "/input history_global_next"); gui_keyboard_default_bind (/* m-a */ "meta-a", "/input jump_smart"); gui_keyboard_default_bind (/* m-j,m-l */ "meta-jmeta-l", "/input jump_last_buffer"); - gui_keyboard_default_bind (/* m-j,m-p */ "meta-jmeta-p", "/input jump_previous_buffer"); gui_keyboard_default_bind (/* m-j,m-r */ "meta-jmeta-r", "/server raw"); gui_keyboard_default_bind (/* m-h */ "meta-h", "/input hotlist_clear"); gui_keyboard_default_bind (/* m-k */ "meta-k", "/input grab_key"); - gui_keyboard_default_bind (/* m-s */ "meta-s", "/server switch"); gui_keyboard_default_bind (/* m-u */ "meta-u", "/input scroll_unread"); gui_keyboard_default_bind (/* ^S^U */ "ctrl-Sctrl-U", "/input set_unread"); gui_keyboard_default_bind (/* ^Cb */ "ctrl-Cb", "/input insert \\x02"); gui_keyboard_default_bind (/* ^Cc */ "ctrl-Cc", "/input insert \\x03"); - gui_keyboard_default_bind (/* ^Cc */ "ctrl-Ci", "/input insert \\x1D"); + gui_keyboard_default_bind (/* ^Ci */ "ctrl-Ci", "/input insert \\x1D"); gui_keyboard_default_bind (/* ^Co */ "ctrl-Co", "/input insert \\x0F"); gui_keyboard_default_bind (/* ^Cr */ "ctrl-Cr", "/input insert \\x12"); gui_keyboard_default_bind (/* ^Cu */ "ctrl-Cu", "/input insert \\x15"); diff --git a/src/gui/curses/gui-curses-window.c b/src/gui/curses/gui-curses-window.c index 5bf42f16b..7c20cc1a6 100644 --- a/src/gui/curses/gui-curses-window.c +++ b/src/gui/curses/gui-curses-window.c @@ -43,6 +43,7 @@ #include "../gui-hotlist.h" #include "../gui-input.h" #include "../gui-main.h" +#include "../gui-line.h" #include "../gui-nicklist.h" #include "gui-curses.h" @@ -488,12 +489,11 @@ gui_window_switch_to_buffer (struct t_gui_window *window, if (!gui_ok) return; - if (window->buffer->num_displayed > 0) - window->buffer->num_displayed--; + gui_buffer_add_value_num_displayed (window->buffer, -1); old_buffer = window->buffer; - if (window->buffer != buffer) + if (window->buffer->number != buffer->number) { window->start_line = NULL; window->start_line_pos = 0; @@ -506,19 +506,19 @@ gui_window_switch_to_buffer (struct t_gui_window *window, { if (window->buffer->num_displayed == 0) { - window->buffer->last_read_line = window->buffer->last_line; - window->buffer->first_line_not_read = 0; + window->buffer->lines->last_read_line = window->buffer->lines->last_line; + window->buffer->lines->first_line_not_read = 0; } - if (buffer->last_read_line == buffer->last_line) + if (buffer->lines->last_read_line == buffer->lines->last_line) { - buffer->last_read_line = NULL; - buffer->first_line_not_read = 0; + buffer->lines->last_read_line = NULL; + buffer->lines->first_line_not_read = 0; } } } window->buffer = buffer; - buffer->num_displayed++; + gui_buffer_add_value_num_displayed (buffer, 1); gui_hotlist_remove_buffer (buffer); @@ -558,6 +558,8 @@ gui_window_switch_to_buffer (struct t_gui_window *window, window->scroll_lines_after = 0; } + gui_buffer_set_active_buffer (buffer); + for (ptr_bar_window = window->bar_windows; ptr_bar_window; ptr_bar_window = ptr_bar_window->next_bar_window) { @@ -812,7 +814,7 @@ gui_window_scroll_top (struct t_gui_window *window) case GUI_BUFFER_TYPE_FORMATTED: if (!window->first_line_displayed) { - window->start_line = gui_chat_get_first_line_displayed (window->buffer); + window->start_line = gui_line_get_first_displayed (window->buffer); window->start_line_pos = 0; window->scroll_reset_allowed = 1; gui_buffer_ask_chat_refresh (window->buffer, 2); @@ -857,7 +859,7 @@ gui_window_scroll_bottom (struct t_gui_window *window) break; case GUI_BUFFER_TYPE_FREE: window->start_line = NULL; - if (window->buffer->lines_count > window->win_chat_height) + if (window->buffer->lines->lines_count > window->win_chat_height) { snprintf (scroll, sizeof (scroll), "-%d", window->win_chat_height - 1); @@ -1015,7 +1017,7 @@ gui_window_split_horizontal (struct t_gui_window *window, int percentage) window->win_height_pct = 100 - percentage; /* assign same buffer for new window (top window) */ - new_window->buffer->num_displayed++; + gui_buffer_add_value_num_displayed (new_window->buffer, 1); window->refresh_needed = 1; new_window->refresh_needed = 1; @@ -1059,7 +1061,7 @@ gui_window_split_vertical (struct t_gui_window *window, int percentage) window->win_width_pct = 100 - percentage; /* assign same buffer for new window (right window) */ - new_window->buffer->num_displayed++; + gui_buffer_add_value_num_displayed (new_window->buffer, 1); window->refresh_needed = 1; new_window->refresh_needed = 1; diff --git a/src/gui/gtk/gui-gtk-bar-window.c b/src/gui/gtk/gui-gtk-bar-window.c index a7eacbd4f..95a6e9850 100644 --- a/src/gui/gtk/gui-gtk-bar-window.c +++ b/src/gui/gtk/gui-gtk-bar-window.c @@ -30,7 +30,6 @@ #include "../../core/wee-log.h" #include "../gui-bar.h" #include "../gui-bar-window.h" -#include "../gui-chat.h" #include "../gui-color.h" #include "../gui-window.h" #include "gui-gtk.h" diff --git a/src/gui/gtk/gui-gtk-chat.c b/src/gui/gtk/gui-gtk-chat.c index 7b009f83c..2cdd395a7 100644 --- a/src/gui/gtk/gui-gtk-chat.c +++ b/src/gui/gtk/gui-gtk-chat.c @@ -34,6 +34,7 @@ #include "../gui-chat.h" #include "../gui-color.h" #include "../gui-main.h" +#include "../gui-line.h" #include "../gui-window.h" #include "gui-gtk.h" @@ -358,7 +359,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, struct t_gui_line **l /* if looking backward, start at last line of buffer */ if (backward) { - *line = window->buffer->last_line; + *line = window->buffer->lines->last_line; if (!(*line)) return; current_size = gui_chat_display_line (window, *line, 0, 1); @@ -369,7 +370,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, struct t_gui_line **l /* if looking forward, start at first line of buffer */ else { - *line = window->buffer->lines; + *line = window->buffer->lines->first_line; if (!(*line)) return; *line_pos = 0; @@ -425,7 +426,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window, struct t_gui_line **l if (backward) { /* first line reached */ - *line = window->buffer->lines; + *line = window->buffer->lines->first_line; *line_pos = 0; } else diff --git a/src/gui/gtk/gui-gtk-color.c b/src/gui/gtk/gui-gtk-color.c index c40c342aa..b25e7baed 100644 --- a/src/gui/gtk/gui-gtk-color.c +++ b/src/gui/gtk/gui-gtk-color.c @@ -31,7 +31,6 @@ #include "../../core/wee-config.h" #include "../../core/wee-string.h" #include "../gui-color.h" -#include "../gui-chat.h" #include "gui-gtk.h" diff --git a/src/gui/gtk/gui-gtk-window.c b/src/gui/gtk/gui-gtk-window.c index ecb836257..2d64dddfe 100644 --- a/src/gui/gtk/gui-gtk-window.c +++ b/src/gui/gtk/gui-gtk-window.c @@ -34,6 +34,7 @@ #include "../gui-buffer.h" #include "../gui-chat.h" #include "../gui-hotlist.h" +#include "../gui-line.h" #include "../gui-nicklist.h" #include "../gui-main.h" #include "gui-gtk.h" @@ -195,8 +196,7 @@ gui_window_switch_to_buffer (struct t_gui_window *window, { GtkTextIter start, end; - if (window->buffer->num_displayed > 0) - window->buffer->num_displayed--; + gui_buffer_add_value_num_displayed (window->buffer, -1); if (window->buffer != buffer) { @@ -211,13 +211,13 @@ gui_window_switch_to_buffer (struct t_gui_window *window, { if (window->buffer->num_displayed == 0) { - window->buffer->last_read_line = window->buffer->last_line; - window->buffer->first_line_not_read = 0; + window->buffer->lines->last_read_line = window->buffer->lines->last_line; + window->buffer->lines->first_line_not_read = 0; } - if (buffer->last_read_line == buffer->last_line) + if (buffer->lines->last_read_line == buffer->lines->last_line) { - buffer->last_read_line = NULL; - buffer->first_line_not_read = 0; + buffer->lines->last_read_line = NULL; + buffer->lines->first_line_not_read = 0; } } } @@ -245,7 +245,7 @@ gui_window_switch_to_buffer (struct t_gui_window *window, window->start_line = NULL; window->start_line_pos = 0; - buffer->num_displayed++; + gui_buffer_add_value_num_displayed (buffer, 1); gui_hotlist_remove_buffer (buffer); } @@ -376,7 +376,7 @@ gui_window_scroll_top (struct t_gui_window *window) if (!window->first_line_displayed) { - window->start_line = window->buffer->lines; + window->start_line = window->buffer->lines->first_line; window->start_line_pos = 0; gui_chat_draw (window->buffer, 0); } @@ -502,7 +502,7 @@ gui_window_split_horizontal (struct t_gui_window *window, int percentage) window->win_height_pct = 100 - percentage; /* assign same buffer for new window (top window) */ - new_window->buffer->num_displayed++; + gui_buffer_add_value_num_displayed (new_window->buffer, 1); gui_window_switch_to_buffer (window, window->buffer, 1); @@ -546,7 +546,7 @@ gui_window_split_vertical (struct t_gui_window *window, int percentage) window->win_width_pct = 100 - percentage; /* assign same buffer for new window (right window) */ - new_window->buffer->num_displayed++; + gui_buffer_add_value_num_displayed (new_window->buffer, 1); gui_window_switch_to_buffer (window, window->buffer, 1); diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index f78dcea16..73a233db6 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -45,6 +45,7 @@ #include "gui-filter.h" #include "gui-hotlist.h" #include "gui-keyboard.h" +#include "gui-line.h" #include "gui-nicklist.h" #include "gui-window.h" @@ -881,7 +882,7 @@ gui_bar_item_default_buffer_filter (void *data, struct t_gui_bar_item *item, if (!window) window = gui_current_window; - if (!gui_filters_enabled || !gui_filters || !window->buffer->lines_hidden) + if (!gui_filters_enabled || !gui_filters || !window->buffer->lines->lines_hidden) return NULL; snprintf (buf, sizeof (buf), @@ -1366,6 +1367,10 @@ gui_bar_item_init () gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NUMBER]); gui_bar_item_hook_signal ("buffer_moved", gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NUMBER]); + gui_bar_item_hook_signal ("buffer_merged", + gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NUMBER]); + gui_bar_item_hook_signal ("buffer_unmerged", + gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NUMBER]); /* buffer name */ gui_bar_item_new (NULL, diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index e933e48ef..373451276 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -49,6 +49,7 @@ #include "gui-input.h" #include "gui-keyboard.h" #include "gui-layout.h" +#include "gui-line.h" #include "gui-main.h" #include "gui-nicklist.h" #include "gui-window.h" @@ -394,6 +395,8 @@ gui_buffer_new (struct t_weechat_plugin *plugin, /* init buffer */ new_buffer->plugin = plugin; new_buffer->plugin_name_for_upgrade = NULL; + new_buffer->merge_for_upgrade = NULL; + /* number will be set later (when inserting buffer in list) */ new_buffer->layout_number = gui_layout_buffer_get_number (gui_layout_buffers, plugin_get_name (plugin), @@ -403,6 +406,7 @@ gui_buffer_new (struct t_weechat_plugin *plugin, new_buffer->type = GUI_BUFFER_TYPE_FORMATTED; new_buffer->notify = CONFIG_INTEGER(config_look_buffer_notify_default); new_buffer->num_displayed = 0; + new_buffer->active = 1; new_buffer->print_hooks_enabled = 1; /* close callback */ @@ -412,14 +416,10 @@ gui_buffer_new (struct t_weechat_plugin *plugin, /* title */ new_buffer->title = NULL; - /* chat lines (formatted) */ - new_buffer->lines = NULL; - new_buffer->last_line = NULL; - new_buffer->last_read_line = NULL; - new_buffer->first_line_not_read = 0; - new_buffer->lines_count = 0; - new_buffer->lines_hidden = 0; - new_buffer->prefix_max_length = 0; + /* chat content */ + new_buffer->own_lines = gui_lines_alloc (); + new_buffer->mixed_lines = NULL; + new_buffer->lines = new_buffer->own_lines; new_buffer->time_for_each_line = 1; new_buffer->chat_refresh_needed = 2; @@ -653,9 +653,9 @@ gui_buffer_get_integer (struct t_gui_buffer *buffer, const char *property) else if (string_strcasecmp (property, "notify") == 0) return buffer->notify; else if (string_strcasecmp (property, "lines_hidden") == 0) - return buffer->lines_hidden; + return buffer->lines->lines_hidden; else if (string_strcasecmp (property, "prefix_max_length") == 0) - return buffer->prefix_max_length; + return buffer->lines->prefix_max_length; else if (string_strcasecmp (property, "time_for_each_line") == 0) return buffer->time_for_each_line; else if (string_strcasecmp (property, "text_search") == 0) @@ -776,7 +776,7 @@ gui_buffer_set_type (struct t_gui_buffer *buffer, enum t_gui_buffer_type type) if (buffer->type == type) return; - gui_chat_line_free_all (buffer); + gui_line_free_all (buffer); buffer->type = type; gui_buffer_ask_chat_refresh (buffer, 2); @@ -915,11 +915,11 @@ gui_buffer_set_unread (struct t_gui_buffer *buffer) if (buffer->type == GUI_BUFFER_TYPE_FORMATTED) { - refresh = ((buffer->last_read_line != NULL) - && (buffer->last_read_line != buffer->last_line)); + refresh = ((buffer->lines->last_read_line != NULL) + && (buffer->lines->last_read_line != buffer->lines->last_line)); - buffer->last_read_line = buffer->last_line; - buffer->first_line_not_read = (buffer->last_read_line) ? 0 : 1; + buffer->lines->last_read_line = buffer->lines->last_line; + buffer->lines->first_line_not_read = (buffer->lines->last_read_line) ? 0 : 1; if (refresh) gui_buffer_ask_chat_refresh (buffer, 2); @@ -1116,6 +1116,28 @@ gui_buffer_set_pointer (struct t_gui_buffer *buffer, const char *property, } /* + * gui_buffer_add_value_num_displayed: add value to "num_displayed" variable + * for a buffer (value can be negative) + */ + +void +gui_buffer_add_value_num_displayed (struct t_gui_buffer *buffer, int value) +{ + struct t_gui_buffer *ptr_buffer; + + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == buffer->number) + { + ptr_buffer->num_displayed += value; + if (ptr_buffer->num_displayed < 0) + ptr_buffer->num_displayed = 0; + } + } +} + +/* * gui_buffer_search_main: get main buffer (weechat one, created at startup) * return first buffer if not found */ @@ -1132,8 +1154,8 @@ gui_buffer_search_main () return ptr_buffer; } - /* buffer not found, return first buffer by default */ - return gui_buffers; + /* buffer not found (should never occur!) */ + return NULL; } /* @@ -1298,6 +1320,29 @@ gui_buffer_search_by_number (int number) } /* + * gui_buffer_count_merged_buffers: return number of merged buffers (buffers + * with same number) + */ + +int +gui_buffer_count_merged_buffers (int number) +{ + struct t_gui_buffer *ptr_buffer; + int count; + + count = 0; + + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == number) + count++; + } + + return count; +} + +/* * gui_buffer_is_scrolled: return 1 if all windows displaying buffer are scrolled * (user doesn't see end of buffer) * return 0 if at least one window is NOT scrolled @@ -1345,7 +1390,7 @@ gui_buffer_clear (struct t_gui_buffer *buffer) return; /* remove all lines */ - gui_chat_line_free_all (buffer); + gui_line_free_all (buffer); /* remove any scroll for buffer */ for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) @@ -1397,6 +1442,10 @@ gui_buffer_close (struct t_gui_buffer *buffer) { (void)(buffer->close_callback) (buffer->close_callback_data, buffer); } + + /* first unmerge buffer if it is merged to at least one other buffer */ + if (gui_buffer_count_merged_buffers (buffer->number) > 1) + gui_buffer_unmerge (buffer, -1); if (!weechat_quit) { @@ -1465,7 +1514,7 @@ gui_buffer_close (struct t_gui_buffer *buffer) } /* free all lines */ - gui_chat_line_free_all (buffer); + gui_line_free_all (buffer); /* free some data */ if (buffer->title) @@ -1531,7 +1580,8 @@ gui_buffer_switch_by_number (struct t_gui_window *window, int number) /* search for buffer in the list */ for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) { - if ((ptr_buffer != window->buffer) && (number == ptr_buffer->number)) + if ((ptr_buffer != window->buffer) && (number == ptr_buffer->number) + && ptr_buffer->active) { gui_window_switch_to_buffer (window, ptr_buffer, 1); return; @@ -1540,14 +1590,60 @@ gui_buffer_switch_by_number (struct t_gui_window *window, int number) } /* + * gui_buffer_set_active_buffer: set active buffer (when many buffers are + * merged) + */ + +void +gui_buffer_set_active_buffer (struct t_gui_buffer *buffer) +{ + struct t_gui_buffer *ptr_buffer; + + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == buffer->number) + ptr_buffer->active = (ptr_buffer == buffer) ? 1 : 0; + } +} + +/* + * gui_buffer_get_next_active_buffer: get next active buffer (when many buffers + * are merged) + */ + +struct t_gui_buffer * +gui_buffer_get_next_active_buffer (struct t_gui_buffer *buffer) +{ + struct t_gui_buffer *ptr_buffer; + + if (buffer->next_buffer + && (buffer->next_buffer->number == buffer->number)) + return buffer->next_buffer; + else + { + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if ((ptr_buffer != buffer) + && (ptr_buffer->number == buffer->number)) + { + return ptr_buffer; + } + } + } + return buffer; +} + +/* * gui_buffer_move_to_number: move a buffer to another number */ void gui_buffer_move_to_number (struct t_gui_buffer *buffer, int number) { - struct t_gui_buffer *ptr_buffer; - int i; + struct t_gui_buffer *ptr_first_buffer, *ptr_last_buffer, *ptr_buffer; + struct t_gui_buffer *ptr_buffer_pos; char buf1_str[16], buf2_str[16], *argv[2] = { NULL, NULL }; /* if only one buffer then return */ @@ -1561,26 +1657,61 @@ gui_buffer_move_to_number (struct t_gui_buffer *buffer, int number) if (number == buffer->number) return; + ptr_first_buffer = NULL; + ptr_last_buffer = NULL; + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == buffer->number) + { + if (!ptr_first_buffer) + ptr_first_buffer = ptr_buffer; + ptr_last_buffer = ptr_buffer; + } + } + + /* error when looking for buffers */ + if (!ptr_first_buffer || !ptr_last_buffer) + return; + + /* if group of buffers found is all buffers, then we can't move buffers! */ + if ((ptr_first_buffer == gui_buffers) && (ptr_last_buffer == last_gui_buffer)) + return; + snprintf (buf2_str, sizeof (buf2_str) - 1, "%d", buffer->number); - /* remove buffer from list */ - if (buffer == gui_buffers) + /* remove buffer(s) from list */ + if (ptr_first_buffer == gui_buffers) { - gui_buffers = buffer->next_buffer; + gui_buffers = ptr_last_buffer->next_buffer; gui_buffers->prev_buffer = NULL; } - if (buffer == last_gui_buffer) + else if (ptr_last_buffer == last_gui_buffer) { - last_gui_buffer = buffer->prev_buffer; + last_gui_buffer = ptr_first_buffer->prev_buffer; last_gui_buffer->next_buffer = NULL; } - if (buffer->prev_buffer) - (buffer->prev_buffer)->next_buffer = buffer->next_buffer; - if (buffer->next_buffer) - (buffer->next_buffer)->prev_buffer = buffer->prev_buffer; + if (ptr_first_buffer->prev_buffer) + (ptr_first_buffer->prev_buffer)->next_buffer = ptr_last_buffer->next_buffer; + if (ptr_last_buffer->next_buffer) + (ptr_last_buffer->next_buffer)->prev_buffer = ptr_first_buffer->prev_buffer; + + /* compute "number - 1" for all buffers after buffer(s) */ + for (ptr_buffer = ptr_last_buffer->next_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number--; + } if (number == 1) { + for (ptr_buffer = ptr_first_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number = 1; + if (ptr_buffer == ptr_last_buffer) + break; + } gui_buffers->prev_buffer = buffer; buffer->prev_buffer = NULL; buffer->next_buffer = gui_buffers; @@ -1588,43 +1719,51 @@ gui_buffer_move_to_number (struct t_gui_buffer *buffer, int number) } else { - /* assign new number to all buffers */ - i = 1; - for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) - { - ptr_buffer->number = i++; - } - /* search for new position in the list */ - for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) + for (ptr_buffer_pos = gui_buffers; ptr_buffer_pos; + ptr_buffer_pos = ptr_buffer_pos->next_buffer) { - if (ptr_buffer->number == number) + if (ptr_buffer_pos->number == number) break; } - if (ptr_buffer) + if (ptr_buffer_pos) { /* insert before buffer found */ - buffer->prev_buffer = ptr_buffer->prev_buffer; - buffer->next_buffer = ptr_buffer; - if (ptr_buffer->prev_buffer) - (ptr_buffer->prev_buffer)->next_buffer = buffer; - ptr_buffer->prev_buffer = buffer; + for (ptr_buffer = ptr_first_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number = ptr_buffer_pos->number; + if (ptr_buffer == ptr_last_buffer) + break; + } + ptr_first_buffer->prev_buffer = ptr_buffer_pos->prev_buffer; + ptr_last_buffer->next_buffer = ptr_buffer_pos; + if (ptr_buffer_pos->prev_buffer) + (ptr_buffer_pos->prev_buffer)->next_buffer = ptr_first_buffer; + ptr_buffer_pos->prev_buffer = ptr_last_buffer; } else { /* number not found (too big)? => add to end */ - buffer->prev_buffer = last_gui_buffer; - buffer->next_buffer = NULL; - last_gui_buffer->next_buffer = buffer; - last_gui_buffer = buffer; + for (ptr_buffer = ptr_first_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number = last_gui_buffer->number + 1; + if (ptr_buffer == ptr_last_buffer) + break; + } + ptr_first_buffer->prev_buffer = last_gui_buffer; + ptr_last_buffer->next_buffer = NULL; + last_gui_buffer->next_buffer = ptr_first_buffer; + last_gui_buffer = ptr_last_buffer; } } - /* assign new number to all buffers */ - i = 1; - for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) + /* compute "number + 1" for all buffers after buffer(s) */ + for (ptr_buffer = ptr_last_buffer->next_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) { - ptr_buffer->number = i++; + ptr_buffer->number++; } snprintf (buf1_str, sizeof (buf1_str) - 1, "%d", buffer->number); @@ -1636,6 +1775,176 @@ gui_buffer_move_to_number (struct t_gui_buffer *buffer, int number) } /* + * gui_buffer_merge: merge a buffer to another buffer + */ + +void +gui_buffer_merge (struct t_gui_buffer *buffer, + struct t_gui_buffer *target_buffer) +{ + struct t_gui_buffer *ptr_buffer; + int target_number; + + /* if only one buffer then return */ + if (gui_buffers == last_gui_buffer) + return; + + if ((buffer == target_buffer) || (buffer->number == target_buffer->number)) + return; + + if (gui_buffer_count_merged_buffers (buffer->number) > 1) + gui_buffer_unmerge (buffer, -1); + + /* check if current buffer and target buffers are type "formatted" */ + if ((buffer->type != GUI_BUFFER_TYPE_FORMATTED) + || (target_buffer->type != GUI_BUFFER_TYPE_FORMATTED)) + { + gui_chat_printf (NULL, + _("%sError: it is only possible to merge buffers " + "with formatted content"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); + return; + } + + /* move buffer immediately after number we want to merge to */ + target_number = (buffer->number < target_buffer->number) ? + target_buffer->number : target_buffer->number + 1; + if (buffer->number != target_number) + gui_buffer_move_to_number (buffer, target_number); + + /* change number */ + buffer->number--; + + /* mix lines */ + gui_line_mix_buffers (buffer); + + /* set buffer as active in merged buffers group */ + gui_buffer_set_active_buffer (buffer); + + /* compute "number - 1" for next buffers */ + for (ptr_buffer = buffer->next_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number--; + } + + gui_window_ask_refresh (1); + + hook_signal_send ("buffer_merged", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); +} + +/* + * gui_buffer_unmerge: unmerge a buffer from group of merged buffers + * if number >= 1, then buffer is moved to this number, + * otherwise it is moved to buffer->number + 1 + */ + +void +gui_buffer_unmerge (struct t_gui_buffer *buffer, int number) +{ + int num_merged; + struct t_gui_buffer *ptr_buffer; + + /* if only one buffer then return */ + if (gui_buffers == last_gui_buffer) + return; + + num_merged = gui_buffer_count_merged_buffers (buffer->number); + + /* can't unmerge if buffer is not merged to at least one buffer */ + if (num_merged < 2) + return; + + /* by default, we move buffer to buffer->number + 1 */ + if ((number < 1) || (number == buffer->number)) + { + number = buffer->number + 1; + } + else + { + if (number > last_gui_buffer->number + 1) + number = last_gui_buffer->number + 1; + } + + if (num_merged == 2) + { + /* only one buffer will remain, so it will not be merged any more */ + gui_line_mixed_free_all (buffer); + gui_lines_free (buffer->mixed_lines); + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == buffer->number) + { + ptr_buffer->active = 1; + ptr_buffer->mixed_lines = NULL; + ptr_buffer->lines = ptr_buffer->own_lines; + } + } + } + else + { + /* remove this buffer from mixed_lines, but keep other buffers merged */ + ptr_buffer = gui_buffer_get_next_active_buffer (buffer); + if (ptr_buffer) + gui_buffer_set_active_buffer (ptr_buffer); + gui_line_mixed_free_buffer (buffer); + buffer->mixed_lines = NULL; + buffer->lines = buffer->own_lines; + } + + /* remove buffer from list */ + if (buffer->prev_buffer) + (buffer->prev_buffer)->next_buffer = buffer->next_buffer; + if (buffer->next_buffer) + (buffer->next_buffer)->prev_buffer = buffer->prev_buffer; + if (gui_buffers == buffer) + gui_buffers = buffer->next_buffer; + if (last_gui_buffer == buffer) + last_gui_buffer = buffer->prev_buffer; + + /* move buffer */ + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number >= number) + break; + } + if (ptr_buffer) + { + /* insert buffer into the list (before buffer found) */ + buffer->prev_buffer = ptr_buffer->prev_buffer; + buffer->next_buffer = ptr_buffer; + if (ptr_buffer->prev_buffer) + (ptr_buffer->prev_buffer)->next_buffer = buffer; + else + gui_buffers = buffer; + ptr_buffer->prev_buffer = buffer; + } + else + { + /* add buffer to the end */ + buffer->prev_buffer = last_gui_buffer; + buffer->next_buffer = NULL; + last_gui_buffer->next_buffer = buffer; + last_gui_buffer = buffer; + } + buffer->active = 1; + buffer->number = number; + for (ptr_buffer = buffer->next_buffer; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + ptr_buffer->number++; + } + + gui_window_ask_refresh (1); + + hook_signal_send ("buffer_unmerged", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); +} + +/* * gui_buffer_visited_search: search a visited buffer in list of visited buffers */ @@ -1867,11 +2176,11 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "print_hooks_enabled", buffer->print_hooks_enabled)) return 0; - if (!infolist_new_var_integer (ptr_item, "first_line_not_read", buffer->first_line_not_read)) + if (!infolist_new_var_integer (ptr_item, "first_line_not_read", buffer->lines->first_line_not_read)) return 0; - if (!infolist_new_var_integer (ptr_item, "lines_hidden", buffer->lines_hidden)) + if (!infolist_new_var_integer (ptr_item, "lines_hidden", buffer->lines->lines_hidden)) return 0; - if (!infolist_new_var_integer (ptr_item, "prefix_max_length", buffer->prefix_max_length)) + if (!infolist_new_var_integer (ptr_item, "prefix_max_length", buffer->lines->prefix_max_length)) return 0; if (!infolist_new_var_integer (ptr_item, "time_for_each_line", buffer->time_for_each_line)) return 0; @@ -1939,78 +2248,6 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, } /* - * gui_buffer_line_add_to_infolist: add a buffer line in an infolist - * return 1 if ok, 0 if error - */ - -int -gui_buffer_line_add_to_infolist (struct t_infolist *infolist, - struct t_gui_buffer *buffer, - struct t_gui_line *line) -{ - struct t_infolist_item *ptr_item; - int i, length; - char option_name[64], *tags; - - if (!infolist || !line) - return 0; - - ptr_item = infolist_new_item (infolist); - if (!ptr_item) - return 0; - - if (!infolist_new_var_time (ptr_item, "date", line->date)) - return 0; - if (!infolist_new_var_time (ptr_item, "date_printed", line->date)) - return 0; - if (!infolist_new_var_string (ptr_item, "str_time", line->str_time)) - return 0; - - /* write tags */ - if (!infolist_new_var_integer (ptr_item, "tags_count", line->tags_count)) - return 0; - length = 0; - for (i = 0; i < line->tags_count; i++) - { - snprintf (option_name, sizeof (option_name), "tag_%05d", i + 1); - if (!infolist_new_var_string (ptr_item, option_name, - line->tags_array[i])) - return 0; - length += strlen (line->tags_array[i]) + 1; - } - tags = malloc (length + 1); - if (!tags) - return 0; - tags[0] = '\0'; - for (i = 0; i < line->tags_count; i++) - { - strcat (tags, line->tags_array[i]); - if (i < line->tags_count - 1) - strcat (tags, ","); - } - if (!infolist_new_var_string (ptr_item, "tags", tags)) - { - free (tags); - return 0; - } - free (tags); - - if (!infolist_new_var_integer (ptr_item, "displayed", line->displayed)) - return 0; - if (!infolist_new_var_integer (ptr_item, "highlight", line->highlight)) - return 0; - if (!infolist_new_var_string (ptr_item, "prefix", line->prefix)) - return 0; - if (!infolist_new_var_string (ptr_item, "message", line->message)) - return 0; - if (!infolist_new_var_integer (ptr_item, "last_read_line", - (buffer->last_read_line == line) ? 1 : 0)) - return 0; - - return 1; -} - -/* * gui_buffer_dump_hexa: dump content of buffer as hexa data in log file */ @@ -2025,11 +2262,12 @@ gui_buffer_dump_hexa (struct t_gui_buffer *buffer) log_printf ("[buffer dump hexa (addr:0x%lx)]", buffer); num_line = 1; - for (ptr_line = buffer->lines; ptr_line; ptr_line = ptr_line->next_line) + for (ptr_line = buffer->lines->first_line; ptr_line; + ptr_line = ptr_line->next_line) { /* display line without colors */ - message_without_colors = (ptr_line->message) ? - gui_color_decode (ptr_line->message, NULL) : NULL; + message_without_colors = (ptr_line->data->message) ? + gui_color_decode (ptr_line->data->message, NULL) : NULL; log_printf (""); log_printf (" line %d: %s", num_line, @@ -2037,13 +2275,13 @@ gui_buffer_dump_hexa (struct t_gui_buffer *buffer) message_without_colors : "(null)"); if (message_without_colors) free (message_without_colors); - tags = string_build_with_exploded ((const char **)ptr_line->tags_array, ","); + tags = string_build_with_exploded ((const char **)ptr_line->data->tags_array, ","); log_printf (" tags: %s", (tags) ? tags : "(none)"); if (tags) free (tags); /* display raw message for line */ - if (ptr_line->message) + if (ptr_line->data->message) { log_printf (""); log_printf (" raw data for line %d (with color codes):", @@ -2051,15 +2289,15 @@ gui_buffer_dump_hexa (struct t_gui_buffer *buffer) msg_pos = 0; hexa_pos = 0; ascii_pos = 0; - while (ptr_line->message[msg_pos]) + while (ptr_line->data->message[msg_pos]) { snprintf (hexa + hexa_pos, 4, "%02X ", - (unsigned char)(ptr_line->message[msg_pos])); + (unsigned char)(ptr_line->data->message[msg_pos])); hexa_pos += 3; snprintf (ascii + ascii_pos, 3, "%c ", - ((((unsigned char)ptr_line->message[msg_pos]) < 32) - || (((unsigned char)ptr_line->message[msg_pos]) > 127)) ? - '.' : (unsigned char)(ptr_line->message[msg_pos])); + ((((unsigned char)ptr_line->data->message[msg_pos]) < 32) + || (((unsigned char)ptr_line->data->message[msg_pos]) > 127)) ? + '.' : (unsigned char)(ptr_line->data->message[msg_pos])); ascii_pos += 2; if (ascii_pos == 32) { @@ -2106,17 +2344,16 @@ gui_buffer_print_log () log_printf (" type . . . . . . . . . : %d", ptr_buffer->type); log_printf (" notify . . . . . . . . : %d", ptr_buffer->notify); log_printf (" num_displayed. . . . . : %d", ptr_buffer->num_displayed); + log_printf (" active . . . . . . . . : %d", ptr_buffer->active); log_printf (" print_hooks_enabled. . : %d", ptr_buffer->print_hooks_enabled); log_printf (" close_callback . . . . : 0x%lx", ptr_buffer->close_callback); log_printf (" close_callback_data. . : 0x%lx", ptr_buffer->close_callback_data); log_printf (" title. . . . . . . . . : '%s'", ptr_buffer->title); + log_printf (" own_lines. . . . . . . : 0x%lx", ptr_buffer->own_lines); + gui_lines_print_log (ptr_buffer->own_lines); + log_printf (" mixed_lines. . . . . . : 0x%lx", ptr_buffer->mixed_lines); + gui_lines_print_log (ptr_buffer->mixed_lines); log_printf (" lines. . . . . . . . . : 0x%lx", ptr_buffer->lines); - log_printf (" last_line. . . . . . . : 0x%lx", ptr_buffer->last_line); - log_printf (" last_read_line . . . . : 0x%lx", ptr_buffer->last_read_line); - log_printf (" first_line_not_read. . : %d", ptr_buffer->first_line_not_read); - log_printf (" lines_count. . . . . . : %d", ptr_buffer->lines_count); - log_printf (" lines_hidden . . . . . : %d", ptr_buffer->lines_hidden); - log_printf (" prefix_max_length. . . : %d", ptr_buffer->prefix_max_length); log_printf (" time_for_each_line . . : %d", ptr_buffer->time_for_each_line); log_printf (" chat_refresh_needed. . : %d", ptr_buffer->chat_refresh_needed); log_printf (" nicklist . . . . . . . : %d", ptr_buffer->nicklist); @@ -2150,6 +2387,8 @@ gui_buffer_print_log () log_printf (" highlight_tags_array . : 0x%lx", ptr_buffer->highlight_tags_array); log_printf (" keys . . . . . . . . . : 0x%lx", ptr_buffer->keys); log_printf (" last_key . . . . . . . : 0x%lx", ptr_buffer->last_key); + 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); @@ -2184,31 +2423,31 @@ gui_buffer_print_log () log_printf (""); log_printf (" => last 100 lines:"); num = 0; - ptr_line = ptr_buffer->last_line; + ptr_line = ptr_buffer->lines->last_line; while (ptr_line && (num < 100)) { num++; ptr_line = ptr_line->prev_line; } if (!ptr_line) - ptr_line = ptr_buffer->lines; + ptr_line = ptr_buffer->lines->first_line; else ptr_line = ptr_line->next_line; while (ptr_line) { num--; - tags = string_build_with_exploded ((const char **)ptr_line->tags_array, ","); + tags = string_build_with_exploded ((const char **)ptr_line->data->tags_array, ","); log_printf (" line N-%05d: y:%d, str_time:'%s', tags:'%s', " "displayed:%d, highlight:%d, refresh_needed:%d, prefix:'%s'", - num, ptr_line->y, ptr_line->str_time, + num, ptr_line->data->y, ptr_line->data->str_time, (tags) ? tags : "", - (int)(ptr_line->displayed), - (int) (ptr_line->highlight), - (int)(ptr_line->refresh_needed), - ptr_line->prefix); + (int)(ptr_line->data->displayed), + (int)(ptr_line->data->highlight), + (int)(ptr_line->data->refresh_needed), + ptr_line->data->prefix); log_printf (" data: '%s'", - ptr_line->message); + ptr_line->data->message); if (tags) free (tags); diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h index c46033d6f..58c251d6c 100644 --- a/src/gui/gui-buffer.h +++ b/src/gui/gui-buffer.h @@ -49,24 +49,6 @@ enum t_gui_buffer_notify /* buffer structures */ -struct t_gui_line -{ - int y; /* line position (for free buffer) */ - time_t date; /* date/time of line (may be past) */ - time_t date_printed; /* date/time when weechat print it */ - char *str_time; /* time string (for display) */ - int tags_count; /* number of tags for line */ - char **tags_array; /* tags for line */ - char displayed; /* 1 if line is displayed */ - char highlight; /* 1 if line has highlight */ - char refresh_needed; /* 1 if refresh asked (free buffer) */ - char *prefix; /* prefix for line (may be NULL) */ - int prefix_length; /* prefix length (on screen) */ - char *message; /* line content (after prefix) */ - struct t_gui_line *prev_line; /* link to previous line */ - struct t_gui_line *next_line; /* link to next line */ -}; - struct t_gui_buffer_local_var { char *name; /* variable name */ @@ -83,6 +65,10 @@ struct t_gui_buffer to store plugin name, then restore plugin pointer when plugin is loaded */ char *plugin_name_for_upgrade; /* plugin name when upgrading */ + /* when upgrading, we use this pointer to remember that this buffer + must merge with another buffer (it's done when all buffers are + restored) */ + struct t_gui_buffer *merge_for_upgrade; int number; /* buffer number (for jump/switch) */ int layout_number; /* the number of buffer saved in */ @@ -95,6 +81,9 @@ struct t_gui_buffer /* 2 = highlight + msg */ /* 3 = highlight + msg + join/part */ int num_displayed; /* number of windows displaying buf. */ + int active; /* it is 0 only if buffers are */ + /* merged and that this one is not */ + /* selected buffer */ int print_hooks_enabled; /* 1 if print hooks are enabled */ /* close callback */ @@ -106,13 +95,10 @@ struct t_gui_buffer char *title; /* buffer title */ /* chat content */ - struct t_gui_line *lines; /* lines of chat window */ - struct t_gui_line *last_line; /* last line of chat window */ - struct t_gui_line *last_read_line; /* last read line before jump */ - int first_line_not_read; /* if 1, marker is before first line */ - int lines_count; /* number of lines in the buffer */ - int lines_hidden; /* 1 if at least one line is hidden */ - int prefix_max_length; /* length for prefix align */ + struct t_gui_lines *own_lines; /* lines (for this buffer only) */ + struct t_gui_lines *mixed_lines; /* mixed lines (if buffers merged) */ + struct t_gui_lines *lines; /* pointer to "own_lines" or */ + /* "mixed_lines" */ int time_for_each_line; /* time is displayed for each line? */ int chat_refresh_needed; /* refresh for chat is needed ? */ /* (1=refresh, 2=erase+refresh) */ @@ -230,6 +216,8 @@ extern void gui_buffer_set (struct t_gui_buffer *buffer, const char *property, const char *value); extern void gui_buffer_set_pointer (struct t_gui_buffer *buffer, const char *property, void *pointer); +extern void gui_buffer_add_value_num_displayed (struct t_gui_buffer *buffer, + int value); extern struct t_gui_buffer *gui_buffer_search_main (); extern struct t_gui_buffer *gui_buffer_search_by_name (const char *plugin, const char *name); @@ -242,7 +230,12 @@ extern void gui_buffer_clear_all (); extern void gui_buffer_close (struct t_gui_buffer *buffer); extern void gui_buffer_switch_by_number (struct t_gui_window *window, int number); +extern void gui_buffer_set_active_buffer (struct t_gui_buffer *buffer); +extern struct t_gui_buffer *gui_buffer_get_next_active_buffer (struct t_gui_buffer *buffer); extern void gui_buffer_move_to_number (struct t_gui_buffer *buffer, int number); +extern void gui_buffer_merge (struct t_gui_buffer *buffer, + struct t_gui_buffer *target_buffer); +extern void gui_buffer_unmerge (struct t_gui_buffer *buffer, int number); extern struct t_gui_buffer_visited *gui_buffer_visited_search_by_number (int number); extern void gui_buffer_visited_remove (struct t_gui_buffer_visited *buffer_visited); extern void gui_buffer_visited_remove_by_buffer (struct t_gui_buffer *buffer); @@ -251,9 +244,6 @@ extern int gui_buffer_visited_get_index_previous (); extern int gui_buffer_visited_get_index_next (); extern int gui_buffer_add_to_infolist (struct t_infolist *infolist, struct t_gui_buffer *buffer); -extern int gui_buffer_line_add_to_infolist (struct t_infolist *infolist, - struct t_gui_buffer *buffer, - struct t_gui_line *line); extern void gui_buffer_dump_hexa (struct t_gui_buffer *buffer); extern void gui_buffer_print_log (); diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c index ab881fcb0..80f11e611 100644 --- a/src/gui/gui-chat.c +++ b/src/gui/gui-chat.c @@ -41,7 +41,7 @@ #include "gui-buffer.h" #include "gui-color.h" #include "gui-filter.h" -#include "gui-hotlist.h" +#include "gui-line.h" #include "gui-main.h" #include "gui-window.h" @@ -359,420 +359,20 @@ gui_chat_change_time_format () for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) { - for (ptr_line = ptr_buffer->lines; ptr_line; + for (ptr_line = ptr_buffer->lines->first_line; ptr_line; ptr_line = ptr_line->next_line) { - if (ptr_line->date != 0) + if (ptr_line->data->date != 0) { - if (ptr_line->str_time) - free (ptr_line->str_time); - ptr_line->str_time = gui_chat_get_time_string (ptr_line->date); + if (ptr_line->data->str_time) + free (ptr_line->data->str_time); + ptr_line->data->str_time = gui_chat_get_time_string (ptr_line->data->date); } } } } /* - * gui_chat_get_line_align: get alignment for a line - */ - -int -gui_chat_get_line_align (struct t_gui_buffer *buffer, struct t_gui_line *line, - int with_suffix) -{ - int time_length, length_suffix; - - time_length = (buffer->time_for_each_line) ? gui_chat_time_length : 0; - - if (CONFIG_INTEGER(config_look_prefix_align) == CONFIG_LOOK_PREFIX_ALIGN_NONE) - return time_length + 1 + line->prefix_length + 2; - - length_suffix = 0; - if (with_suffix) - { - if (CONFIG_STRING(config_look_prefix_suffix) - && CONFIG_STRING(config_look_prefix_suffix)[0]) - length_suffix = gui_chat_strlen_screen (CONFIG_STRING(config_look_prefix_suffix)) + 1; - } - return time_length + ((buffer->prefix_max_length > 0) ? 1 : 0) + - + (((CONFIG_INTEGER(config_look_prefix_align_max) > 0) - && (buffer->prefix_max_length > CONFIG_INTEGER(config_look_prefix_align_max))) ? - CONFIG_INTEGER(config_look_prefix_align_max) : buffer->prefix_max_length) - + length_suffix + 1; -} - -/* - * gui_chat_line_displayed: return 1 if line is displayed (no filter on line, - * or filters disabled), 0 if line is hidden - */ - -int -gui_chat_line_displayed (struct t_gui_line *line) -{ - /* line is hidden if filters are enabled and flag "displayed" is not set */ - if (gui_filters_enabled && !line->displayed) - return 0; - - /* in all other cases, line is displayed */ - return 1; -} - -/* - * gui_chat_get_first_line_displayed: get first line displayed of a buffer - */ - -struct t_gui_line * -gui_chat_get_first_line_displayed (struct t_gui_buffer *buffer) -{ - struct t_gui_line *ptr_line; - - ptr_line = buffer->lines; - while (ptr_line && !gui_chat_line_displayed (ptr_line)) - { - ptr_line = ptr_line->next_line; - } - - return ptr_line; -} - -/* - * gui_chat_get_last_line_displayed: get last line displayed of a buffer - */ - -struct t_gui_line * -gui_chat_get_last_line_displayed (struct t_gui_buffer *buffer) -{ - struct t_gui_line *ptr_line; - - ptr_line = buffer->last_line; - while (ptr_line && !gui_chat_line_displayed (ptr_line)) - { - ptr_line = ptr_line->prev_line; - } - - return ptr_line; -} - -/* - * gui_chat_get_prev_line_displayed: get previous line displayed - */ - -struct t_gui_line * -gui_chat_get_prev_line_displayed (struct t_gui_line *line) -{ - if (line) - { - line = line->prev_line; - while (line && !gui_chat_line_displayed (line)) - { - line = line->prev_line; - } - } - return line; -} - -/* - * gui_chat_get_next_line_displayed: get next line displayed - */ - -struct t_gui_line * -gui_chat_get_next_line_displayed (struct t_gui_line *line) -{ - if (line) - { - line = line->next_line; - while (line && !gui_chat_line_displayed (line)) - { - line = line->next_line; - } - } - return line; -} - -/* - * gui_chat_line_search: search for text in a line - */ - -int -gui_chat_line_search (struct t_gui_line *line, const char *text, - int case_sensitive) -{ - char *prefix, *message; - int rc; - - if (!line || !line->message || !text || !text[0]) - return 0; - - rc = 0; - - if (line->prefix) - { - prefix = gui_color_decode (line->prefix, NULL); - if (prefix) - { - if ((case_sensitive && (strstr (prefix, text))) - || (!case_sensitive && (string_strcasestr (prefix, text)))) - rc = 1; - free (prefix); - } - } - - if (!rc) - { - message = gui_color_decode (line->message, NULL); - if (message) - { - if ((case_sensitive && (strstr (message, text))) - || (!case_sensitive && (string_strcasestr (message, text)))) - rc = 1; - free (message); - } - } - - return rc; -} - -/* - * gui_chat_line_match_regex: return 1 if message matches regex - * 0 if it doesn't match - */ - -int -gui_chat_line_match_regex (struct t_gui_line *line, regex_t *regex_prefix, - regex_t *regex_message) -{ - char *prefix, *message; - int match_prefix, match_message; - - if (!line || (!regex_prefix && !regex_message)) - return 0; - - prefix = NULL; - message = NULL; - - match_prefix = 1; - match_message = 1; - - if (line->prefix) - { - prefix = gui_color_decode (line->prefix, NULL); - if (!prefix - || (regex_prefix && (regexec (regex_prefix, prefix, 0, NULL, 0) != 0))) - match_prefix = 0; - } - else - { - if (regex_prefix) - match_prefix = 0; - } - - if (line->message) - { - message = gui_color_decode (line->message, NULL); - if (!message - || (regex_message && (regexec (regex_message, message, 0, NULL, 0) != 0))) - match_message = 0; - } - else - { - if (regex_message) - match_message = 0; - } - - if (prefix) - free (prefix); - if (message) - free (message); - - return (match_prefix && match_message); -} - -/* - * gui_chat_line_match_tags: return 1 if line matches tags - * 0 if it doesn't match any tag in array - */ - -int -gui_chat_line_match_tags (struct t_gui_line *line, int tags_count, - char **tags_array) -{ - int i, j; - - if (!line) - return 0; - - if (line->tags_count == 0) - return 0; - - for (i = 0; i < tags_count; i++) - { - for (j = 0; j < line->tags_count; j++) - { - /* check tag */ - if (string_match (line->tags_array[j], - tags_array[i], - 0)) - return 1; - } - } - - return 0; -} - -/* - * gui_chat_line_has_highlight: return 1 if given message contains highlight (with - * a string in global highlight or buffer highlight) - */ - -int -gui_chat_line_has_highlight (struct t_gui_buffer *buffer, - struct t_gui_line *line) -{ - int rc, i; - char *msg_no_color; - - /* highlights are disabled on this buffer? (special value "-" means that - buffer does not want any highlight) */ - if (buffer->highlight_words && (strcmp (buffer->highlight_words, "-") == 0)) - return 0; - - /* check if highlight is disabled for line */ - for (i = 0; i < line->tags_count; i++) - { - if (strcmp (line->tags_array[i], GUI_CHAT_TAG_NO_HIGHLIGHT) == 0) - return 0; - } - - /* check that line matches highlight tags, if any (if no tag is specified, - then any tag is allowed) */ - if (buffer->highlight_tags_count > 0) - { - if (!gui_chat_line_match_tags (line, - buffer->highlight_tags_count, - buffer->highlight_tags_array)) - return 0; - } - - /* remove color codes from line message */ - msg_no_color = gui_color_decode (line->message, NULL); - if (!msg_no_color) - return 0; - - /* there is highlight on line if one of global highlight words matches line - or one of buffer highlight words matches line */ - rc = (string_has_highlight (msg_no_color, - CONFIG_STRING(config_look_highlight)) || - string_has_highlight (msg_no_color, - buffer->highlight_words)); - - free (msg_no_color); - - return rc; -} - -/* - * gui_chat_line_free: delete a formatted line from a buffer - */ - -void -gui_chat_line_free (struct t_gui_buffer *buffer, struct t_gui_line *line) -{ - int update_prefix_max_length; - struct t_gui_line *ptr_line; - struct t_gui_window *ptr_win; - - update_prefix_max_length = (line->prefix_length == buffer->prefix_max_length); - - /* reset scroll for any window starting with this line */ - for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) - { - if (ptr_win->start_line == line) - { - ptr_win->start_line = ptr_win->start_line->next_line; - ptr_win->start_line_pos = 0; - gui_buffer_ask_chat_refresh (buffer, 2); - } - } - - /* move read marker if it was on line we are removing */ - if (buffer->last_read_line == line) - { - buffer->last_read_line = buffer->last_read_line->prev_line; - buffer->first_line_not_read = (buffer->last_read_line) ? 0 : 1; - gui_buffer_ask_chat_refresh (buffer, 1); - } - - /* free data */ - if (line->str_time) - free (line->str_time); - if (line->tags_array) - string_free_exploded (line->tags_array); - if (line->prefix) - free (line->prefix); - if (line->message) - free (line->message); - - /* remove line from lines list */ - if (line->prev_line) - (line->prev_line)->next_line = line->next_line; - if (line->next_line) - (line->next_line)->prev_line = line->prev_line; - if (buffer->lines == line) - buffer->lines = line->next_line; - if (buffer->last_line == line) - buffer->last_line = line->prev_line; - - free (line); - - buffer->lines_count--; - - if (update_prefix_max_length) - { - buffer->prefix_max_length = 0; - for (ptr_line = buffer->lines; ptr_line; - ptr_line = ptr_line->next_line) - { - if (ptr_line->prefix_length > buffer->prefix_max_length) - buffer->prefix_max_length = ptr_line->prefix_length; - } - } -} - -/* - * gui_chat_line_free_all: delete all formatted lines from a buffer - */ - -void -gui_chat_line_free_all (struct t_gui_buffer *buffer) -{ - while (buffer->lines) - { - gui_chat_line_free (buffer, buffer->lines); - } -} - -/* - * gui_chat_line_get_notify_level: get notify level for a line - */ - -int -gui_chat_line_get_notify_level (struct t_gui_line *line) -{ - int i; - - for (i = 0; i < line->tags_count; i++) - { - if (string_strcasecmp (line->tags_array[i], "notify_highlight") == 0) - return GUI_HOTLIST_HIGHLIGHT; - if (string_strcasecmp (line->tags_array[i], "notify_private") == 0) - return GUI_HOTLIST_PRIVATE; - if (string_strcasecmp (line->tags_array[i], "notify_message") == 0) - return GUI_HOTLIST_MESSAGE; - } - return GUI_HOTLIST_LOW; -} - -/* * gui_chat_build_string_prefix_message: build a string with prefix and message */ @@ -783,22 +383,22 @@ gui_chat_build_string_prefix_message (struct t_gui_line *line) int length; length = 0; - if (line->prefix) - length += strlen (line->prefix); + if (line->data->prefix) + length += strlen (line->data->prefix); length++; - if (line->message) - length += strlen (line->message); + if (line->data->message) + length += strlen (line->data->message); length++; string = malloc (length); if (string) { string[0] = '\0'; - if (line->prefix) - strcat (string, line->prefix); + if (line->data->prefix) + strcat (string, line->data->prefix); strcat (string, "\t"); - if (line->message) - strcat (string, line->message); + if (line->data->message) + strcat (string, line->data->message); } if (string) @@ -815,219 +415,6 @@ gui_chat_build_string_prefix_message (struct t_gui_line *line) } /* - * gui_chat_line_add: add a new line for a buffer - */ - -struct t_gui_line * -gui_chat_line_add (struct t_gui_buffer *buffer, time_t date, - time_t date_printed, const char *tags, - const char *prefix, const char *message) -{ - struct t_gui_line *new_line; - struct t_gui_window *ptr_win; - char *message_for_signal; - int notify_level; - - new_line = malloc (sizeof (*new_line)); - if (!new_line) - { - log_printf (_("Not enough memory for new line")); - return NULL; - } - - /* fill data in new line */ - new_line->y = 0; - new_line->date = date; - new_line->date_printed = date_printed; - new_line->str_time = (date == 0) ? - NULL : gui_chat_get_time_string (date); - if (tags) - { - new_line->tags_array = string_explode (tags, ",", 0, 0, - &new_line->tags_count); - } - else - { - new_line->tags_count = 0; - new_line->tags_array = NULL; - } - new_line->refresh_needed = 0; - new_line->prefix = (prefix) ? - strdup (prefix) : ((date != 0) ? strdup ("") : NULL); - new_line->prefix_length = (prefix) ? - gui_chat_strlen_screen (prefix) : 0; - new_line->message = (message) ? strdup (message) : strdup (""); - new_line->highlight = gui_chat_line_has_highlight (buffer, new_line); - - /* add line to lines list */ - if (!buffer->lines) - buffer->lines = new_line; - else - buffer->last_line->next_line = new_line; - new_line->prev_line = buffer->last_line; - new_line->next_line = NULL; - buffer->last_line = new_line; - buffer->lines_count++; - - /* check if line is filtered or not */ - new_line->displayed = gui_filter_check_line (buffer, new_line); - if (new_line->displayed) - { - if (new_line->prefix_length > buffer->prefix_max_length) - buffer->prefix_max_length = new_line->prefix_length; - if (new_line->highlight) - { - gui_hotlist_add (buffer, GUI_HOTLIST_HIGHLIGHT, NULL, 1); - if (!weechat_upgrading) - { - message_for_signal = gui_chat_build_string_prefix_message (new_line); - if (message_for_signal) - { - hook_signal_send ("weechat_highlight", - WEECHAT_HOOK_SIGNAL_STRING, - message_for_signal); - free (message_for_signal); - } - } - } - else - { - notify_level = gui_chat_line_get_notify_level (new_line); - if (!weechat_upgrading && (notify_level == GUI_HOTLIST_PRIVATE)) - { - message_for_signal = gui_chat_build_string_prefix_message (new_line); - if (message_for_signal) - { - hook_signal_send ("weechat_pv", - WEECHAT_HOOK_SIGNAL_STRING, - message_for_signal); - free (message_for_signal); - } - } - gui_hotlist_add (buffer, notify_level, NULL, 1); - } - } - else - { - if (!buffer->lines_hidden) - { - buffer->lines_hidden = 1; - hook_signal_send ("buffer_lines_hidden", - WEECHAT_HOOK_SIGNAL_POINTER, buffer); - } - } - - /* remove one line if necessary */ - if ((CONFIG_INTEGER(config_history_max_lines) > 0) - && (buffer->lines_count > CONFIG_INTEGER(config_history_max_lines))) - { - gui_chat_line_free (buffer, buffer->lines); - for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) - { - if ((ptr_win->buffer == buffer) - && (buffer->lines_count < ptr_win->win_chat_height)) - { - gui_buffer_ask_chat_refresh (buffer, 2); - break; - } - } - } - - return new_line; -} - -/* - * gui_chat_line_add_y: add or update a line for a buffer with free content - */ - -void -gui_chat_line_add_y (struct t_gui_buffer *buffer, int y, const char *message) -{ - struct t_gui_line *ptr_line, *new_line; - - if (!message || !message[0]) - return; - - /* search if line exists for "y" */ - for (ptr_line = buffer->lines; ptr_line; - ptr_line = ptr_line->next_line) - { - if (ptr_line->y >= y) - break; - } - - if (!ptr_line || (ptr_line->y > y)) - { - new_line = malloc (sizeof (*new_line)); - if (!new_line) - { - log_printf (_("Not enough memory for new line")); - return; - } - - buffer->lines_count++; - - /* fill data in new line */ - new_line->y = y; - new_line->date = 0; - new_line->date_printed = 0; - new_line->str_time = NULL; - new_line->tags_count = 0; - new_line->tags_array = NULL; - new_line->refresh_needed = 1; - new_line->prefix = NULL; - new_line->prefix_length = 0; - new_line->message = NULL; - new_line->highlight = 0; - - /* add line to lines list */ - if (ptr_line) - { - /* add before line found */ - new_line->prev_line = ptr_line->prev_line; - new_line->next_line = ptr_line; - if (ptr_line->prev_line) - (ptr_line->prev_line)->next_line = new_line; - else - buffer->lines = new_line; - ptr_line->prev_line = new_line; - } - else - { - /* add at end of list */ - new_line->prev_line = buffer->last_line; - if (buffer->lines) - buffer->last_line->next_line = new_line; - else - buffer->lines = new_line; - buffer->last_line = new_line; - new_line->next_line = NULL; - } - - ptr_line = new_line; - } - - /* set message for line */ - if (ptr_line->message) - free (ptr_line->message); - ptr_line->message = strdup (message); - - /* check if line is filtered or not */ - ptr_line->displayed = gui_filter_check_line (buffer, ptr_line); - if (!ptr_line->displayed) - { - if (!buffer->lines_hidden) - { - buffer->lines_hidden = 1; - hook_signal_send ("buffer_lines_hidden", - WEECHAT_HOOK_SIGNAL_POINTER, buffer); - } - } - - ptr_line->refresh_needed = 1; -} - -/* * gui_chat_printf_date_tags: display a message in a buffer with optional * date and tags * Info: this function works only with formatted @@ -1082,7 +469,7 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date, date = date_printed; if (gui_init_ok) - ptr_line = buffer->last_line; + ptr_line = buffer->lines->last_line; at_least_one_message_printed = 0; @@ -1153,12 +540,12 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date, if (gui_init_ok) { - gui_chat_line_add (buffer, (display_time) ? date : 0, - (display_time) ? date_printed : 0, - tags, pos_prefix, ptr_msg); - if (buffer->last_line && buffer->print_hooks_enabled) + gui_line_add (buffer, (display_time) ? date : 0, + (display_time) ? date_printed : 0, + tags, pos_prefix, ptr_msg); + if (buffer->lines->last_line && buffer->print_hooks_enabled) { - hook_print_exec (buffer, buffer->last_line); + hook_print_exec (buffer, buffer->lines->last_line); } at_least_one_message_printed = 1; } @@ -1219,15 +606,15 @@ gui_chat_printf_y (struct t_gui_buffer *buffer, int y, const char *message, ...) { if (gui_init_ok) { - for (ptr_line = buffer->lines; ptr_line; + for (ptr_line = buffer->lines->first_line; ptr_line; ptr_line = ptr_line->next_line) { - if (ptr_line->y >= y) + if (ptr_line->data->y >= y) break; } - if (ptr_line && (ptr_line->y == y)) + if (ptr_line && (ptr_line->data->y == y)) { - gui_chat_line_free (buffer, ptr_line); + gui_line_free (buffer, ptr_line); gui_buffer_ask_chat_refresh (buffer, 2); } } @@ -1236,7 +623,7 @@ gui_chat_printf_y (struct t_gui_buffer *buffer, int y, const char *message, ...) { if (gui_init_ok) { - gui_chat_line_add_y (buffer, y, gui_chat_buffer); + gui_line_add_y (buffer, y, gui_chat_buffer); gui_buffer_ask_chat_refresh (buffer, 1); } else diff --git a/src/gui/gui-chat.h b/src/gui/gui-chat.h index 12ddeb1b7..791184b17 100644 --- a/src/gui/gui-chat.h +++ b/src/gui/gui-chat.h @@ -20,8 +20,6 @@ #ifndef __WEECHAT_GUI_CHAT_H #define __WEECHAT_GUI_CHAT_H 1 -#include <regex.h> - struct t_gui_window; struct t_gui_buffer; struct t_gui_line; @@ -60,31 +58,9 @@ extern void gui_chat_get_word_info (struct t_gui_window *window, int *word_end_offset, int *word_length_with_spaces, int *word_length); +extern char *gui_chat_get_time_string (time_t date); extern void gui_chat_change_time_format (); -extern int gui_chat_get_line_align (struct t_gui_buffer *buffer, - struct t_gui_line *line, - int with_suffix); -extern int gui_chat_line_displayed (struct t_gui_line *line); -extern struct t_gui_line *gui_chat_get_first_line_displayed (struct t_gui_buffer *buffer); -extern struct t_gui_line *gui_chat_get_last_line_displayed (struct t_gui_buffer *buffer); -extern struct t_gui_line *gui_chat_get_prev_line_displayed (struct t_gui_line *line); -extern struct t_gui_line *gui_chat_get_next_line_displayed (struct t_gui_line *line); -extern int gui_chat_line_search (struct t_gui_line *line, const char *text, - int case_sensitive); -extern int gui_chat_line_match_regex (struct t_gui_line *line, - regex_t *regex_prefix, - regex_t *regex_message); -extern int gui_chat_line_match_tags (struct t_gui_line *line, int tags_count, - char **tags_array); -extern void gui_chat_line_free (struct t_gui_buffer *buffer, - struct t_gui_line *line); -extern void gui_chat_line_free_all (struct t_gui_buffer *buffer); -extern struct t_gui_line *gui_chat_line_add (struct t_gui_buffer *buffer, - time_t date, - time_t date_printed, - const char *tags, - const char *prefix, - const char *message); +extern char *gui_chat_build_string_prefix_message (struct t_gui_line *line); extern void gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date, const char *tags, const char *message, ...); diff --git a/src/gui/gui-color.h b/src/gui/gui-color.h index 50cee70d0..7feae6497 100644 --- a/src/gui/gui-color.h +++ b/src/gui/gui-color.h @@ -58,6 +58,7 @@ enum t_gui_color_enum GUI_COLOR_CHAT_READ_MARKER, GUI_COLOR_CHAT_TEXT_FOUND, GUI_COLOR_CHAT_VALUE, + GUI_COLOR_CHAT_PREFIX_BUFFER, /* number of colors */ GUI_COLOR_NUM_COLORS, diff --git a/src/gui/gui-filter.c b/src/gui/gui-filter.c index 5e823e3b0..4906f7a93 100644 --- a/src/gui/gui-filter.c +++ b/src/gui/gui-filter.c @@ -35,7 +35,7 @@ #include "../plugins/plugin.h" #include "gui-filter.h" #include "gui-buffer.h" -#include "gui-chat.h" +#include "gui-line.h" struct t_gui_filter *gui_filters = NULL; /* first filter */ @@ -54,9 +54,9 @@ gui_filter_line_has_tag_no_filter (struct t_gui_line *line) { int i; - for (i = 0; i < line->tags_count; i++) + for (i = 0; i < line->data->tags_count; i++) { - if (strcmp (line->tags_array[i], GUI_FILTER_TAG_NO_FILTER) == 0) + if (strcmp (line->data->tags_array[i], GUI_FILTER_TAG_NO_FILTER) == 0) return 1; } @@ -92,17 +92,17 @@ gui_filter_check_line (struct t_gui_buffer *buffer, struct t_gui_line *line) && string_match (buffer->name, ptr_filter->buffer_name, 0)) { if ((strcmp (ptr_filter->tags, "*") == 0) - || (gui_chat_line_match_tags (line, - ptr_filter->tags_count, - ptr_filter->tags_array))) + || (gui_line_match_tags (line, + ptr_filter->tags_count, + ptr_filter->tags_array))) { /* check line with regex */ if (!ptr_filter->regex_prefix && !ptr_filter->regex_message) return 0; - if (gui_chat_line_match_regex (line, - ptr_filter->regex_prefix, - ptr_filter->regex_message)) + if (gui_line_match_regex (line, + ptr_filter->regex_prefix, + ptr_filter->regex_message)) return 0; } } @@ -125,32 +125,32 @@ gui_filter_buffer (struct t_gui_buffer *buffer) lines_hidden = 0; - buffer->prefix_max_length = 0; + buffer->lines->prefix_max_length = 0; - for (ptr_line = buffer->lines; ptr_line; + for (ptr_line = buffer->lines->first_line; ptr_line; ptr_line = ptr_line->next_line) { line_displayed = gui_filter_check_line (buffer, ptr_line); if (line_displayed - && (ptr_line->prefix_length > buffer->prefix_max_length)) + && (ptr_line->data->prefix_length > buffer->lines->prefix_max_length)) { - buffer->prefix_max_length = ptr_line->prefix_length; + buffer->lines->prefix_max_length = ptr_line->data->prefix_length; } /* force chat refresh if at least one line changed */ - if (ptr_line->displayed != line_displayed) + if (ptr_line->data->displayed != line_displayed) gui_buffer_ask_chat_refresh (buffer, 2); - ptr_line->displayed = line_displayed; + ptr_line->data->displayed = line_displayed; if (!line_displayed) lines_hidden = 1; } - if (buffer->lines_hidden != lines_hidden) + if (buffer->lines->lines_hidden != lines_hidden) { - buffer->lines_hidden = lines_hidden; + buffer->lines->lines_hidden = lines_hidden; hook_signal_send ("buffer_lines_hidden", WEECHAT_HOOK_SIGNAL_POINTER, buffer); } diff --git a/src/gui/gui-hotlist.c b/src/gui/gui-hotlist.c index ae14bb5d3..2d8cf38fb 100644 --- a/src/gui/gui-hotlist.c +++ b/src/gui/gui-hotlist.c @@ -293,7 +293,8 @@ gui_hotlist_add (struct t_gui_buffer *buffer, int priority, if (!gui_hotlist_check_buffer_notify (buffer, priority)) return; - if ((ptr_hotlist = gui_hotlist_search (gui_hotlist, buffer))) + ptr_hotlist = gui_hotlist_search (gui_hotlist, buffer); + if (ptr_hotlist) { /* return if priority is greater or equal than the one to add */ if (ptr_hotlist->priority >= priority) @@ -395,7 +396,7 @@ void gui_hotlist_remove_buffer (struct t_gui_buffer *buffer) { struct t_gui_hotlist *pos_hotlist; - + pos_hotlist = gui_hotlist_search (gui_hotlist, buffer); if (pos_hotlist) { @@ -453,6 +454,10 @@ gui_hotlist_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "buffer_number", hotlist->buffer->number)) return 0; + if (!infolist_new_var_string (ptr_item, "plugin_name", plugin_get_name (hotlist->buffer->plugin))) + return 0; + if (!infolist_new_var_string (ptr_item, "buffer_name", hotlist->buffer->name)) + return 0; return 1; } diff --git a/src/gui/gui-input.c b/src/gui/gui-input.c index 645ac945b..2429f31eb 100644 --- a/src/gui/gui-input.c +++ b/src/gui/gui-input.c @@ -35,11 +35,11 @@ #include "../plugins/plugin.h" #include "gui-input.h" #include "gui-buffer.h" -#include "gui-chat.h" #include "gui-completion.h" #include "gui-history.h" #include "gui-hotlist.h" #include "gui-keyboard.h" +#include "gui-line.h" #include "gui-window.h" @@ -1239,17 +1239,17 @@ gui_input_scroll_unread () if (CONFIG_STRING(config_look_read_marker) && CONFIG_STRING(config_look_read_marker)[0] && (gui_current_window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) && - (gui_current_window->buffer->first_line_not_read || - (gui_current_window->buffer->last_read_line && - gui_current_window->buffer->last_read_line != gui_current_window->buffer->last_line))) + (gui_current_window->buffer->lines->first_line_not_read || + (gui_current_window->buffer->lines->last_read_line && + gui_current_window->buffer->lines->last_read_line != gui_current_window->buffer->lines->last_line))) { - if (gui_current_window->buffer->first_line_not_read) - gui_current_window->start_line = gui_current_window->buffer->lines; + if (gui_current_window->buffer->lines->first_line_not_read) + gui_current_window->start_line = gui_current_window->buffer->lines->first_line; else - gui_current_window->start_line = gui_current_window->buffer->last_read_line->next_line; + gui_current_window->start_line = gui_current_window->buffer->lines->last_read_line->next_line; gui_current_window->start_line_pos = 0; gui_current_window->first_line_displayed = - (gui_current_window->start_line == gui_chat_get_first_line_displayed (gui_current_window->buffer)); + (gui_current_window->start_line == gui_line_get_first_displayed (gui_current_window->buffer)); gui_buffer_ask_chat_refresh (gui_current_window->buffer, 2); } } @@ -1285,6 +1285,24 @@ gui_input_set_unread_current_buffer () } /* + * gui_input_switch_active_buffer: switch active buffer (when many buffers are + * merged) + */ + +void +gui_input_switch_active_buffer () +{ + struct t_gui_buffer *ptr_buffer; + + ptr_buffer = gui_buffer_get_next_active_buffer (gui_current_window->buffer); + if (ptr_buffer) + { + gui_buffer_set_active_buffer (ptr_buffer); + gui_window_switch_to_buffer (gui_current_window, ptr_buffer, 1); + } +} + +/* * gui_input_insert: insert a string in command line * (many default keys are bound to this function) */ diff --git a/src/gui/gui-input.h b/src/gui/gui-input.h index dcbcc3e67..0a1e4983d 100644 --- a/src/gui/gui-input.h +++ b/src/gui/gui-input.h @@ -66,6 +66,7 @@ extern void gui_input_grab_key (); extern void gui_input_scroll_unread (); extern void gui_input_set_unread (); extern void gui_input_set_unread_current_buffer (); +extern void gui_input_switch_active_buffer (); extern void gui_input_insert (); #endif /* gui-input.h */ diff --git a/src/gui/gui-line.c b/src/gui/gui-line.c new file mode 100644 index 000000000..b73d75805 --- /dev/null +++ b/src/gui/gui-line.c @@ -0,0 +1,1068 @@ +/* + * Copyright (c) 2003-2009 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* gui-line.c: line functions, used by all GUI */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> + +#include "../core/weechat.h" +#include "../core/wee-config.h" +#include "../core/wee-hook.h" +#include "../core/wee-infolist.h" +#include "../core/wee-log.h" +#include "../core/wee-string.h" +#include "../plugins/plugin.h" +#include "gui-line.h" +#include "gui-buffer.h" +#include "gui-chat.h" +#include "gui-color.h" +#include "gui-filter.h" +#include "gui-hotlist.h" +#include "gui-window.h" + + +/* + * gui_lines_alloc: alloc structure "t_gui_lines" and initialize it + */ + +struct t_gui_lines * +gui_lines_alloc () +{ + struct t_gui_lines *new_lines; + + new_lines = malloc (sizeof (*new_lines)); + if (new_lines) + { + new_lines->first_line = NULL; + new_lines->last_line = NULL; + new_lines->last_read_line = NULL; + new_lines->lines_count = 0; + new_lines->first_line_not_read = 0; + new_lines->lines_hidden = 0; + new_lines->buffer_max_length = 0; + new_lines->prefix_max_length = 0; + } + + return new_lines; +} + +/* + * gui_lines_free: free a "t_gui_lines" structure + */ + +void +gui_lines_free (struct t_gui_lines *lines) +{ + free (lines); +} + +/* + * gui_line_get_align: get alignment for a line + */ + +int +gui_line_get_align (struct t_gui_buffer *buffer, struct t_gui_line *line, + int with_suffix) +{ + int length_time, length_buffer, length_suffix; + + /* length of time */ + length_time = (buffer->time_for_each_line) ? gui_chat_time_length : 0; + + /* length of buffer name (when many buffers are merged) */ + if (buffer->mixed_lines) + { + length_buffer = ((CONFIG_INTEGER(config_look_prefix_buffer_align) == CONFIG_LOOK_PREFIX_ALIGN_NONE) + && (CONFIG_INTEGER(config_look_prefix_align) == CONFIG_LOOK_PREFIX_ALIGN_NONE)) ? + gui_chat_strlen_screen (buffer->short_name) + 1 : buffer->mixed_lines->buffer_max_length + 1; + } + else + length_buffer = 0; + + if (CONFIG_INTEGER(config_look_prefix_align) == CONFIG_LOOK_PREFIX_ALIGN_NONE) + return length_time + 1 + length_buffer + line->data->prefix_length + 2; + + length_suffix = 0; + if (with_suffix) + { + if (CONFIG_STRING(config_look_prefix_suffix) + && CONFIG_STRING(config_look_prefix_suffix)[0]) + length_suffix = gui_chat_strlen_screen (CONFIG_STRING(config_look_prefix_suffix)) + 1; + } + + return length_time + ((buffer->lines->prefix_max_length > 0) ? 1 : 0) + + length_buffer + + (((CONFIG_INTEGER(config_look_prefix_align_max) > 0) + && (buffer->lines->prefix_max_length > CONFIG_INTEGER(config_look_prefix_align_max))) ? + CONFIG_INTEGER(config_look_prefix_align_max) : buffer->lines->prefix_max_length) + + length_suffix + 1; +} + +/* + * gui_line_is_displayed: return 1 if line is displayed (no filter on line, + * or filters disabled), 0 if line is hidden + */ + +int +gui_line_is_displayed (struct t_gui_line *line) +{ + /* line is hidden if filters are enabled and flag "displayed" is not set */ + if (gui_filters_enabled && !line->data->displayed) + return 0; + + /* in all other cases, line is displayed */ + return 1; +} + +/* + * gui_line_get_first_displayed: get first line displayed of a buffer + */ + +struct t_gui_line * +gui_line_get_first_displayed (struct t_gui_buffer *buffer) +{ + struct t_gui_line *ptr_line; + + ptr_line = buffer->lines->first_line; + while (ptr_line && !gui_line_is_displayed (ptr_line)) + { + ptr_line = ptr_line->next_line; + } + + return ptr_line; +} + +/* + * gui_line_get_last_displayed: get last line displayed of a buffer + */ + +struct t_gui_line * +gui_line_get_last_displayed (struct t_gui_buffer *buffer) +{ + struct t_gui_line *ptr_line; + + ptr_line = buffer->lines->last_line; + while (ptr_line && !gui_line_is_displayed (ptr_line)) + { + ptr_line = ptr_line->prev_line; + } + + return ptr_line; +} + +/* + * gui_line_get_prev_displayed: get previous line displayed + */ + +struct t_gui_line * +gui_line_get_prev_displayed (struct t_gui_line *line) +{ + if (line) + { + line = line->prev_line; + while (line && !gui_line_is_displayed (line)) + { + line = line->prev_line; + } + } + return line; +} + +/* + * gui_line_get_next_displayed: get next line displayed + */ + +struct t_gui_line * +gui_line_get_next_displayed (struct t_gui_line *line) +{ + if (line) + { + line = line->next_line; + while (line && !gui_line_is_displayed (line)) + { + line = line->next_line; + } + } + return line; +} + +/* + * gui_line_search_text: search for text in a line + */ + +int +gui_line_search_text (struct t_gui_line *line, const char *text, + int case_sensitive) +{ + char *prefix, *message; + int rc; + + if (!line || !line->data->message || !text || !text[0]) + return 0; + + rc = 0; + + if (line->data->prefix) + { + prefix = gui_color_decode (line->data->prefix, NULL); + if (prefix) + { + if ((case_sensitive && (strstr (prefix, text))) + || (!case_sensitive && (string_strcasestr (prefix, text)))) + rc = 1; + free (prefix); + } + } + + if (!rc) + { + message = gui_color_decode (line->data->message, NULL); + if (message) + { + if ((case_sensitive && (strstr (message, text))) + || (!case_sensitive && (string_strcasestr (message, text)))) + rc = 1; + free (message); + } + } + + return rc; +} + +/* + * gui_line_match_regex: return 1 if message matches regex + * 0 if it doesn't match + */ + +int +gui_line_match_regex (struct t_gui_line *line, regex_t *regex_prefix, + regex_t *regex_message) +{ + char *prefix, *message; + int match_prefix, match_message; + + if (!line || (!regex_prefix && !regex_message)) + return 0; + + prefix = NULL; + message = NULL; + + match_prefix = 1; + match_message = 1; + + if (line->data->prefix) + { + prefix = gui_color_decode (line->data->prefix, NULL); + if (!prefix + || (regex_prefix && (regexec (regex_prefix, prefix, 0, NULL, 0) != 0))) + match_prefix = 0; + } + else + { + if (regex_prefix) + match_prefix = 0; + } + + if (line->data->message) + { + message = gui_color_decode (line->data->message, NULL); + if (!message + || (regex_message && (regexec (regex_message, message, 0, NULL, 0) != 0))) + match_message = 0; + } + else + { + if (regex_message) + match_message = 0; + } + + if (prefix) + free (prefix); + if (message) + free (message); + + return (match_prefix && match_message); +} + +/* + * gui_line_match_tags: return 1 if line matches tags + * 0 if it doesn't match any tag in array + */ + +int +gui_line_match_tags (struct t_gui_line *line, int tags_count, + char **tags_array) +{ + int i, j; + + if (!line) + return 0; + + if (line->data->tags_count == 0) + return 0; + + for (i = 0; i < tags_count; i++) + { + for (j = 0; j < line->data->tags_count; j++) + { + /* check tag */ + if (string_match (line->data->tags_array[j], + tags_array[i], + 0)) + return 1; + } + } + + return 0; +} + +/* + * gui_line_has_highlight: return 1 if given message contains highlight (with + * a string in global highlight or buffer highlight) + */ + +int +gui_line_has_highlight (struct t_gui_line *line) +{ + int rc, i; + char *msg_no_color; + + /* highlights are disabled on this buffer? (special value "-" means that + buffer does not want any highlight) */ + if (line->data->buffer->highlight_words + && (strcmp (line->data->buffer->highlight_words, "-") == 0)) + return 0; + + /* check if highlight is disabled for line */ + for (i = 0; i < line->data->tags_count; i++) + { + if (strcmp (line->data->tags_array[i], GUI_CHAT_TAG_NO_HIGHLIGHT) == 0) + return 0; + } + + /* check that line matches highlight tags, if any (if no tag is specified, + then any tag is allowed) */ + if (line->data->buffer->highlight_tags_count > 0) + { + if (!gui_line_match_tags (line, + line->data->buffer->highlight_tags_count, + line->data->buffer->highlight_tags_array)) + return 0; + } + + /* remove color codes from line message */ + msg_no_color = gui_color_decode (line->data->message, NULL); + if (!msg_no_color) + return 0; + + /* there is highlight on line if one of global highlight words matches line + or one of buffer highlight words matches line */ + rc = (string_has_highlight (msg_no_color, + CONFIG_STRING(config_look_highlight)) || + string_has_highlight (msg_no_color, + line->data->buffer->highlight_words)); + + free (msg_no_color); + + return rc; +} + +/* + * gui_line_compute_buffer_max_length: compute "buffer_max_length" for a + * "t_gui_lines" structure + */ + +void +gui_line_compute_buffer_max_length (struct t_gui_buffer *buffer, + struct t_gui_lines *lines) +{ + struct t_gui_buffer *ptr_buffer; + int length; + + lines->buffer_max_length = 0; + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if ((ptr_buffer->number == buffer->number) && ptr_buffer->short_name) + { + length = gui_chat_strlen_screen (ptr_buffer->short_name); + if (length > lines->buffer_max_length) + lines->buffer_max_length = length; + } + } +} + +/* + * gui_line_compute_prefix_max_length: compute "prefix_max_length" for a + * "t_gui_lines" structure + */ + +void +gui_line_compute_prefix_max_length (struct t_gui_lines *lines) +{ + struct t_gui_line *ptr_line; + + lines->prefix_max_length = 0; + for (ptr_line = lines->first_line; ptr_line; + ptr_line = ptr_line->next_line) + { + if (ptr_line->data->prefix_length > lines->prefix_max_length) + lines->prefix_max_length = ptr_line->data->prefix_length; + } +} + +/* + * gui_line_add_to_list: add a line to a "t_gui_lines" structure + */ + +void +gui_line_add_to_list (struct t_gui_lines *lines, + struct t_gui_line *line) +{ + if (!lines->first_line) + lines->first_line = line; + else + (lines->last_line)->next_line = line; + line->prev_line = lines->last_line; + line->next_line = NULL; + lines->last_line = line; + + if (line->data->prefix_length > lines->prefix_max_length) + lines->prefix_max_length = line->data->prefix_length; + + lines->lines_count++; +} + +/* + * gui_line_remove_from_list: remove a line from a "t_gui_lines" structure + */ + +void +gui_line_remove_from_list (struct t_gui_lines *lines, + struct t_gui_line *line, + int free_data) +{ + int update_prefix_max_length; + + update_prefix_max_length = + (line->data->prefix_length == lines->prefix_max_length); + + /* free data */ + if (free_data) + { + if (line->data->str_time) + free (line->data->str_time); + if (line->data->tags_array) + string_free_exploded (line->data->tags_array); + if (line->data->prefix) + free (line->data->prefix); + if (line->data->message) + free (line->data->message); + free (line->data); + } + + /* remove line from list */ + if (line->prev_line) + (line->prev_line)->next_line = line->next_line; + if (line->next_line) + (line->next_line)->prev_line = line->prev_line; + if (lines->first_line == line) + lines->first_line = line->next_line; + if (lines->last_line == line) + lines->last_line = line->prev_line; + + lines->lines_count--; + + free (line); + + /* compute "prefix_max_length" if needed */ + if (update_prefix_max_length) + gui_line_compute_prefix_max_length (lines); +} + +/* + * gui_line_mixed_add: add line to mixed lines for a buffer + */ + +void +gui_line_mixed_add (struct t_gui_lines *lines, + struct t_gui_line_data *line_data) +{ + struct t_gui_line *new_line; + + new_line = malloc (sizeof (*new_line)); + if (new_line) + { + new_line->data = line_data; + gui_line_add_to_list (lines, new_line); + } +} + +/* + * gui_line_mixed_free_buffer: free all mixed lines matching a buffer + */ + +void +gui_line_mixed_free_buffer (struct t_gui_buffer *buffer) +{ + struct t_gui_line *ptr_line, *ptr_next_line; + + if (buffer->mixed_lines) + { + ptr_line = buffer->mixed_lines->first_line; + while (ptr_line) + { + ptr_next_line = ptr_line->next_line; + + if (ptr_line->data->buffer == buffer) + { + gui_line_remove_from_list (buffer->mixed_lines, + ptr_line, + 0); + } + + ptr_line = ptr_next_line; + } + } +} + +/* + * gui_line_mixed_free_all: free all mixed lines in a buffer + */ + +void +gui_line_mixed_free_all (struct t_gui_buffer *buffer) +{ + if (buffer->mixed_lines) + { + while (buffer->mixed_lines->first_line) + { + gui_line_remove_from_list (buffer->mixed_lines, + buffer->mixed_lines->first_line, + 0); + } + } +} + +/* + * gui_line_free: delete a formatted line from a buffer + */ + +void +gui_line_free (struct t_gui_buffer *buffer, struct t_gui_line *line) +{ + struct t_gui_line *ptr_line; + struct t_gui_window *ptr_win; + + /* first remove mixed line if it exists */ + if (buffer->mixed_lines) + { + for (ptr_line = buffer->mixed_lines->first_line; ptr_line; + ptr_line = ptr_line->next_line) + { + if (ptr_line->data == line->data) + { + gui_line_remove_from_list (buffer->mixed_lines, ptr_line, 0); + break; + } + } + } + + /* reset scroll for any window starting with this line */ + for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) + { + if (ptr_win->start_line == line) + { + ptr_win->start_line = ptr_win->start_line->next_line; + ptr_win->start_line_pos = 0; + gui_buffer_ask_chat_refresh (buffer, 2); + } + } + + /* move read marker if it was on line we are removing */ + if (buffer->own_lines->last_read_line == line) + { + buffer->own_lines->last_read_line = buffer->own_lines->last_read_line->prev_line; + buffer->own_lines->first_line_not_read = (buffer->own_lines->last_read_line) ? 0 : 1; + gui_buffer_ask_chat_refresh (buffer, 1); + } + + /* remove line from lines list */ + gui_line_remove_from_list (buffer->own_lines, line, 1); +} + +/* + * gui_line_free_all: delete all formatted lines from a buffer + */ + +void +gui_line_free_all (struct t_gui_buffer *buffer) +{ + while (buffer->own_lines->first_line) + { + gui_line_free (buffer, buffer->own_lines->first_line); + } +} + +/* + * gui_line_get_notify_level: get notify level for a line + */ + +int +gui_line_get_notify_level (struct t_gui_line *line) +{ + int i; + + for (i = 0; i < line->data->tags_count; i++) + { + if (string_strcasecmp (line->data->tags_array[i], "notify_highlight") == 0) + return GUI_HOTLIST_HIGHLIGHT; + if (string_strcasecmp (line->data->tags_array[i], "notify_private") == 0) + return GUI_HOTLIST_PRIVATE; + if (string_strcasecmp (line->data->tags_array[i], "notify_message") == 0) + return GUI_HOTLIST_MESSAGE; + } + return GUI_HOTLIST_LOW; +} + +/* + * gui_line_add: add a new line for a buffer + */ + +struct t_gui_line * +gui_line_add (struct t_gui_buffer *buffer, time_t date, + time_t date_printed, const char *tags, + const char *prefix, const char *message) +{ + struct t_gui_line *new_line; + struct t_gui_line_data *new_line_data; + struct t_gui_window *ptr_win; + char *message_for_signal; + int notify_level; + + new_line = malloc (sizeof (*new_line)); + if (!new_line) + { + log_printf (_("Not enough memory for new line")); + return NULL; + } + + new_line_data = malloc (sizeof (*(new_line->data))); + if (!new_line_data) + { + free (new_line); + log_printf (_("Not enough memory for new line")); + return NULL; + } + new_line->data = new_line_data; + + /* fill data in new line */ + new_line->data->buffer = buffer; + new_line->data->y = 0; + new_line->data->date = date; + new_line->data->date_printed = date_printed; + new_line->data->str_time = (date == 0) ? + NULL : gui_chat_get_time_string (date); + if (tags) + { + new_line->data->tags_array = string_explode (tags, ",", 0, 0, + &new_line->data->tags_count); + } + else + { + new_line->data->tags_count = 0; + new_line->data->tags_array = NULL; + } + new_line->data->refresh_needed = 0; + new_line->data->prefix = (prefix) ? + strdup (prefix) : ((date != 0) ? strdup ("") : NULL); + new_line->data->prefix_length = (prefix) ? + gui_chat_strlen_screen (prefix) : 0; + new_line->data->message = (message) ? strdup (message) : strdup (""); + new_line->data->highlight = gui_line_has_highlight (new_line); + + /* add line to lines list */ + gui_line_add_to_list (buffer->own_lines, new_line); + + /* check if line is filtered or not */ + new_line->data->displayed = gui_filter_check_line (buffer, new_line); + if (new_line->data->displayed) + { + if (new_line->data->highlight) + { + gui_hotlist_add (buffer, GUI_HOTLIST_HIGHLIGHT, NULL, 1); + if (!weechat_upgrading) + { + message_for_signal = gui_chat_build_string_prefix_message (new_line); + if (message_for_signal) + { + hook_signal_send ("weechat_highlight", + WEECHAT_HOOK_SIGNAL_STRING, + message_for_signal); + free (message_for_signal); + } + } + } + else + { + notify_level = gui_line_get_notify_level (new_line); + if (!weechat_upgrading && (notify_level == GUI_HOTLIST_PRIVATE)) + { + message_for_signal = gui_chat_build_string_prefix_message (new_line); + if (message_for_signal) + { + hook_signal_send ("weechat_pv", + WEECHAT_HOOK_SIGNAL_STRING, + message_for_signal); + free (message_for_signal); + } + } + gui_hotlist_add (buffer, notify_level, NULL, 1); + } + } + else + { + if (!buffer->own_lines->lines_hidden) + { + buffer->own_lines->lines_hidden = 1; + if (buffer->mixed_lines) + buffer->mixed_lines->lines_hidden = 1; + hook_signal_send ("buffer_lines_hidden", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); + } + } + + /* add mixed line, if buffer is attched to at least one other buffer */ + if (buffer->mixed_lines) + { + gui_line_mixed_add (buffer->mixed_lines, new_line->data); + } + + /* remove one line if necessary */ + if ((CONFIG_INTEGER(config_history_max_lines) > 0) + && (buffer->own_lines->lines_count > CONFIG_INTEGER(config_history_max_lines))) + { + gui_line_free (buffer, buffer->own_lines->first_line); + for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) + { + if ((ptr_win->buffer == buffer) + && (buffer->own_lines->lines_count < ptr_win->win_chat_height)) + { + gui_buffer_ask_chat_refresh (buffer, 2); + break; + } + } + } + + return new_line; +} + +/* + * gui_line_add_y: add or update a line for a buffer with free content + */ + +void +gui_line_add_y (struct t_gui_buffer *buffer, int y, const char *message) +{ + struct t_gui_line *ptr_line, *new_line; + struct t_gui_line_data *new_line_data; + + if (!message || !message[0]) + return; + + /* search if line exists for "y" */ + for (ptr_line = buffer->own_lines->first_line; ptr_line; + ptr_line = ptr_line->next_line) + { + if (ptr_line->data->y >= y) + break; + } + + if (!ptr_line || (ptr_line->data->y > y)) + { + new_line = malloc (sizeof (*new_line)); + if (!new_line) + { + log_printf (_("Not enough memory for new line")); + return; + } + + new_line_data = malloc (sizeof (*(new_line->data))); + if (!new_line_data) + { + free (new_line); + log_printf (_("Not enough memory for new line")); + return; + } + new_line->data = new_line_data; + + buffer->own_lines->lines_count++; + + /* fill data in new line */ + new_line->data->y = y; + new_line->data->date = 0; + new_line->data->date_printed = 0; + new_line->data->str_time = NULL; + new_line->data->tags_count = 0; + new_line->data->tags_array = NULL; + new_line->data->refresh_needed = 1; + new_line->data->prefix = NULL; + new_line->data->prefix_length = 0; + new_line->data->message = NULL; + new_line->data->highlight = 0; + + /* add line to lines list */ + if (ptr_line) + { + /* add before line found */ + new_line->prev_line = ptr_line->prev_line; + new_line->next_line = ptr_line; + if (ptr_line->prev_line) + (ptr_line->prev_line)->next_line = new_line; + else + buffer->own_lines->first_line = new_line; + ptr_line->prev_line = new_line; + } + else + { + /* add at end of list */ + new_line->prev_line = buffer->own_lines->last_line; + if (buffer->own_lines->first_line) + buffer->own_lines->last_line->next_line = new_line; + else + buffer->own_lines->first_line = new_line; + buffer->own_lines->last_line = new_line; + new_line->next_line = NULL; + } + + ptr_line = new_line; + } + + /* set message for line */ + if (ptr_line->data->message) + free (ptr_line->data->message); + ptr_line->data->message = strdup (message); + + /* check if line is filtered or not */ + ptr_line->data->displayed = gui_filter_check_line (buffer, ptr_line); + if (!ptr_line->data->displayed) + { + if (!buffer->own_lines->lines_hidden) + { + buffer->own_lines->lines_hidden = 1; + hook_signal_send ("buffer_lines_hidden", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); + } + } + + ptr_line->data->refresh_needed = 1; +} + +/* + * gui_line_mix_buffers: mix lines of a buffer (or group of buffers) with a new + * buffer + */ + +void +gui_line_mix_buffers (struct t_gui_buffer *buffer) +{ + struct t_gui_buffer *ptr_buffer, *ptr_buffer_found; + struct t_gui_lines *new_lines; + struct t_gui_line *ptr_line1, *ptr_line2; + + /* search first other buffer with same number */ + ptr_buffer_found = NULL; + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if ((ptr_buffer != buffer) && (ptr_buffer->number == buffer->number)) + { + ptr_buffer_found = ptr_buffer; + break; + } + } + if (!ptr_buffer_found) + return; + + /* mix all lines (sorting by date) to a new structure "new_lines" */ + new_lines = gui_lines_alloc (); + if (!new_lines) + return; + ptr_line1 = ptr_buffer_found->lines->first_line; + ptr_line2 = buffer->lines->first_line; + while (ptr_line1 || ptr_line2) + { + if (!ptr_line1) + { + gui_line_mixed_add (new_lines, ptr_line2->data); + ptr_line2 = ptr_line2->next_line; + } + else + { + if (!ptr_line2) + { + gui_line_mixed_add (new_lines, ptr_line1->data); + ptr_line1 = ptr_line1->next_line; + } + else + { + /* look for older line by comparing time */ + if (ptr_line1->data->date <= ptr_line2->data->date) + { + while (ptr_line1 + && (ptr_line1->data->date <= ptr_line2->data->date)) + { + gui_line_mixed_add (new_lines, ptr_line1->data); + ptr_line1 = ptr_line1->next_line; + } + } + else + { + while (ptr_line2 + && (ptr_line1->data->date > ptr_line2->data->date)) + { + gui_line_mixed_add (new_lines, ptr_line2->data); + ptr_line2 = ptr_line2->next_line; + } + } + } + } + } + + /* compute "prefix_max_length" for mixed lines */ + gui_line_compute_prefix_max_length (new_lines); + + /* compute "buffer_max_length" for mixed lines */ + gui_line_compute_buffer_max_length (buffer, new_lines); + + /* free old mixed lines */ + if (ptr_buffer_found->mixed_lines) + { + gui_line_mixed_free_all (ptr_buffer_found); + free (ptr_buffer_found->mixed_lines); + } + + /* use new structure with mixed lines in all buffers with correct number */ + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->number == buffer->number) + { + ptr_buffer->mixed_lines = new_lines; + ptr_buffer->lines = ptr_buffer->mixed_lines; + } + } +} + +/* + * gui_buffer_line_add_to_infolist: add a buffer line in an infolist + * return 1 if ok, 0 if error + */ + +int +gui_line_add_to_infolist (struct t_infolist *infolist, + struct t_gui_lines *lines, + struct t_gui_line *line) +{ + struct t_infolist_item *ptr_item; + int i, length; + char option_name[64], *tags; + + if (!infolist || !line) + return 0; + + ptr_item = infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!infolist_new_var_time (ptr_item, "date", line->data->date)) + return 0; + if (!infolist_new_var_time (ptr_item, "date_printed", line->data->date_printed)) + return 0; + if (!infolist_new_var_string (ptr_item, "str_time", line->data->str_time)) + return 0; + + /* write tags */ + if (!infolist_new_var_integer (ptr_item, "tags_count", line->data->tags_count)) + return 0; + length = 0; + for (i = 0; i < line->data->tags_count; i++) + { + snprintf (option_name, sizeof (option_name), "tag_%05d", i + 1); + if (!infolist_new_var_string (ptr_item, option_name, + line->data->tags_array[i])) + return 0; + length += strlen (line->data->tags_array[i]) + 1; + } + tags = malloc (length + 1); + if (!tags) + return 0; + tags[0] = '\0'; + for (i = 0; i < line->data->tags_count; i++) + { + strcat (tags, line->data->tags_array[i]); + if (i < line->data->tags_count - 1) + strcat (tags, ","); + } + if (!infolist_new_var_string (ptr_item, "tags", tags)) + { + free (tags); + return 0; + } + free (tags); + + if (!infolist_new_var_integer (ptr_item, "displayed", line->data->displayed)) + return 0; + if (!infolist_new_var_integer (ptr_item, "highlight", line->data->highlight)) + return 0; + if (!infolist_new_var_string (ptr_item, "prefix", line->data->prefix)) + return 0; + if (!infolist_new_var_string (ptr_item, "message", line->data->message)) + return 0; + if (!infolist_new_var_integer (ptr_item, "last_read_line", + (lines->last_read_line == line) ? 1 : 0)) + return 0; + + return 1; +} + +/* + * gui_lines_print_log: print lines structure infos in log (usually for crash dump) + */ + +void +gui_lines_print_log (struct t_gui_lines *lines) +{ + if (lines) + { + log_printf (" first_line . . . . . : 0x%lx", lines->first_line); + log_printf (" last_line. . . . . . : 0x%lx", lines->last_line); + log_printf (" last_read_line . . . : 0x%lx", lines->last_read_line); + log_printf (" lines_count. . . . . . : %d", lines->lines_count); + log_printf (" first_line_not_read. . : %d", lines->first_line_not_read); + log_printf (" lines_hidden . . . . : %d", lines->lines_hidden); + log_printf (" buffer_max_length. . : %d", lines->buffer_max_length); + log_printf (" prefix_max_length. . : %d", lines->prefix_max_length); + } +} diff --git a/src/gui/gui-line.h b/src/gui/gui-line.h new file mode 100644 index 000000000..fe92716c8 --- /dev/null +++ b/src/gui/gui-line.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003-2009 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_GUI_LINE_H +#define __WEECHAT_GUI_LINE_H 1 + +#include <regex.h> + +struct t_infolist; + +/* line structures */ + +struct t_gui_line_data +{ + struct t_gui_buffer *buffer; /* pointer to buffer */ + int y; /* line position (for free buffer) */ + time_t date; /* date/time of line (may be past) */ + time_t date_printed; /* date/time when weechat print it */ + char *str_time; /* time string (for display) */ + int tags_count; /* number of tags for line */ + char **tags_array; /* tags for line */ + char displayed; /* 1 if line is displayed */ + char highlight; /* 1 if line has highlight */ + char refresh_needed; /* 1 if refresh asked (free buffer) */ + char *prefix; /* prefix for line (may be NULL) */ + int prefix_length; /* prefix length (on screen) */ + char *message; /* line content (after prefix) */ +}; + +struct t_gui_line +{ + struct t_gui_line_data *data; /* pointer to line data */ + struct t_gui_line *prev_line; /* link to previous line */ + struct t_gui_line *next_line; /* link to next line */ +}; + +struct t_gui_lines +{ + struct t_gui_line *first_line; /* pointer to first line */ + struct t_gui_line *last_line; /* pointer to last line */ + struct t_gui_line *last_read_line; /* last read line */ + int lines_count; /* number of lines */ + int first_line_not_read; /* if 1, marker is before first line */ + int lines_hidden; /* 1 if at least one line is hidden */ + int buffer_max_length; /* max length for buffer name (for */ + /* mixed lines only) */ + int prefix_max_length; /* max length for prefix align */ +}; + +/* line functions */ + +extern struct t_gui_lines *gui_lines_alloc (); +extern void gui_lines_free (struct t_gui_lines *lines); +extern int gui_line_get_align (struct t_gui_buffer *buffer, + struct t_gui_line *line, + int with_suffix); +extern int gui_line_is_displayed (struct t_gui_line *line); +extern struct t_gui_line *gui_line_get_first_displayed (struct t_gui_buffer *buffer); +extern struct t_gui_line *gui_line_get_last_displayed (struct t_gui_buffer *buffer); +extern struct t_gui_line *gui_line_get_prev_displayed (struct t_gui_line *line); +extern struct t_gui_line *gui_line_get_next_displayed (struct t_gui_line *line); +extern int gui_line_search_text (struct t_gui_line *line, const char *text, + int case_sensitive); +extern int gui_line_match_regex (struct t_gui_line *line, + regex_t *regex_prefix, + regex_t *regex_message); +extern int gui_line_match_tags (struct t_gui_line *line, int tags_count, + char **tags_array); +extern int gui_line_has_highlight (struct t_gui_line *line); +extern void gui_line_mixed_free_buffer (struct t_gui_buffer *buffer); +extern void gui_line_mixed_free_all (struct t_gui_buffer *buffer); +extern void gui_line_free (struct t_gui_buffer *buffer, + struct t_gui_line *line); +extern void gui_line_free_all (struct t_gui_buffer *buffer); +extern int gui_line_get_notify_level (struct t_gui_line *line); +extern struct t_gui_line *gui_line_add (struct t_gui_buffer *buffer, + time_t date, + time_t date_printed, + const char *tags, + const char *prefix, + const char *message); +extern void gui_line_add_y (struct t_gui_buffer *buffer, int y, + const char *message); +extern void gui_line_mix_buffers (struct t_gui_buffer *buffer); +extern int gui_line_add_to_infolist (struct t_infolist *infolist, + struct t_gui_lines *lines, + struct t_gui_line *line); +extern void gui_lines_print_log (struct t_gui_lines *lines); + +#endif /* gui-line.h */ diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c index 91bd37146..d039c8520 100644 --- a/src/gui/gui-window.c +++ b/src/gui/gui-window.c @@ -44,11 +44,11 @@ #include "gui-bar.h" #include "gui-bar-window.h" #include "gui-buffer.h" -#include "gui-chat.h" #include "gui-filter.h" #include "gui-input.h" #include "gui-hotlist.h" #include "gui-layout.h" +#include "gui-line.h" int gui_init_ok = 0; /* = 1 if GUI is initialized*/ @@ -419,8 +419,8 @@ gui_window_set_layout_buffer_name (struct t_gui_window *window, void gui_window_free (struct t_gui_window *window) { - if (window->buffer && (window->buffer->num_displayed > 0)) - window->buffer->num_displayed--; + if (window->buffer) + gui_buffer_add_value_num_displayed (window->buffer, -1); /* free data */ if (window->gui_objects) @@ -524,7 +524,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll) struct t_gui_line *ptr_line; struct tm *date_tmp, line_date, old_line_date; - if (window->buffer->lines) + if (window->buffer->lines->first_line) { direction = 1; number = 0; @@ -579,8 +579,8 @@ gui_window_scroll (struct t_gui_window *window, char *scroll) if (direction < 0) { ptr_line = (window->start_line) ? - window->start_line : window->buffer->last_line; - while (ptr_line && !gui_chat_line_displayed (ptr_line)) + window->start_line : window->buffer->lines->last_line; + while (ptr_line && !gui_line_is_displayed (ptr_line)) { ptr_line = ptr_line->prev_line; } @@ -588,21 +588,21 @@ gui_window_scroll (struct t_gui_window *window, char *scroll) else { ptr_line = (window->start_line) ? - window->start_line : window->buffer->lines; - while (ptr_line && !gui_chat_line_displayed (ptr_line)) + window->start_line : window->buffer->lines->first_line; + while (ptr_line && !gui_line_is_displayed (ptr_line)) { ptr_line = ptr_line->next_line; } } - old_date = ptr_line->date; + old_date = ptr_line->data->date; date_tmp = localtime (&old_date); memcpy (&old_line_date, date_tmp, sizeof (struct tm)); while (ptr_line) { ptr_line = (direction < 0) ? - gui_chat_get_prev_line_displayed (ptr_line) : gui_chat_get_next_line_displayed (ptr_line); + gui_line_get_prev_displayed (ptr_line) : gui_line_get_next_displayed (ptr_line); if (ptr_line) { @@ -614,12 +614,12 @@ gui_window_scroll (struct t_gui_window *window, char *scroll) } else { - date_tmp = localtime (&(ptr_line->date)); + date_tmp = localtime (&(ptr_line->data->date)); memcpy (&line_date, date_tmp, sizeof (struct tm)); - if (old_date > ptr_line->date) - diff_date = old_date - ptr_line->date; + if (old_date > ptr_line->data->date) + diff_date = old_date - ptr_line->data->date; else - diff_date = ptr_line->date - old_date; + diff_date = ptr_line->data->date - old_date; switch (time_letter) { case 's': /* seconds */ @@ -709,7 +709,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll) window->start_line = ptr_line; window->start_line_pos = 0; window->first_line_displayed = - (window->start_line == gui_chat_get_first_line_displayed (window->buffer)); + (window->start_line == gui_line_get_first_displayed (window->buffer)); gui_buffer_ask_chat_refresh (window->buffer, 2); return; } @@ -737,18 +737,18 @@ gui_window_scroll_previous_highlight (struct t_gui_window *window) if ((window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) { - if (window->buffer->lines) + if (window->buffer->lines->first_line) { ptr_line = (window->start_line) ? - window->start_line->prev_line : window->buffer->last_line; + window->start_line->prev_line : window->buffer->lines->last_line; while (ptr_line) { - if (ptr_line->highlight) + if (ptr_line->data->highlight) { window->start_line = ptr_line; window->start_line_pos = 0; window->first_line_displayed = - (window->start_line == window->buffer->lines); + (window->start_line == window->buffer->lines->first_line); gui_buffer_ask_chat_refresh (window->buffer, 2); return; } @@ -770,18 +770,18 @@ gui_window_scroll_next_highlight (struct t_gui_window *window) if ((window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) { - if (window->buffer->lines) + if (window->buffer->lines->first_line) { ptr_line = (window->start_line) ? - window->start_line->next_line : window->buffer->lines->next_line; + window->start_line->next_line : window->buffer->lines->first_line->next_line; while (ptr_line) { - if (ptr_line->highlight) + if (ptr_line->data->highlight) { window->start_line = ptr_line; window->start_line_pos = 0; window->first_line_displayed = - (window->start_line == window->buffer->lines); + (window->start_line == window->buffer->lines->first_line); gui_buffer_ask_chat_refresh (window->buffer, 2); return; } @@ -802,51 +802,51 @@ gui_window_search_text (struct t_gui_window *window) if (window->buffer->text_search == GUI_TEXT_SEARCH_BACKWARD) { - if (window->buffer->lines + if (window->buffer->lines->first_line && window->buffer->input_buffer && window->buffer->input_buffer[0]) { ptr_line = (window->start_line) ? - gui_chat_get_prev_line_displayed (window->start_line) : - gui_chat_get_last_line_displayed (window->buffer); + gui_line_get_prev_displayed (window->start_line) : + gui_line_get_last_displayed (window->buffer); while (ptr_line) { - if (gui_chat_line_search (ptr_line, + if (gui_line_search_text (ptr_line, window->buffer->input_buffer, window->buffer->text_search_exact)) { window->start_line = ptr_line; window->start_line_pos = 0; window->first_line_displayed = - (window->start_line == gui_chat_get_first_line_displayed (window->buffer)); + (window->start_line == gui_line_get_first_displayed (window->buffer)); gui_buffer_ask_chat_refresh (window->buffer, 2); return 1; } - ptr_line = gui_chat_get_prev_line_displayed (ptr_line); + ptr_line = gui_line_get_prev_displayed (ptr_line); } } } else if (window->buffer->text_search == GUI_TEXT_SEARCH_FORWARD) { - if (window->buffer->lines + if (window->buffer->lines->first_line && window->buffer->input_buffer && window->buffer->input_buffer[0]) { ptr_line = (window->start_line) ? - gui_chat_get_next_line_displayed (window->start_line) : - gui_chat_get_first_line_displayed (window->buffer); + gui_line_get_next_displayed (window->start_line) : + gui_line_get_first_displayed (window->buffer); while (ptr_line) { - if (gui_chat_line_search (ptr_line, + if (gui_line_search_text (ptr_line, window->buffer->input_buffer, window->buffer->text_search_exact)) { window->start_line = ptr_line; window->start_line_pos = 0; window->first_line_displayed = - (window->start_line == window->buffer->lines); + (window->start_line == window->buffer->lines->first_line); gui_buffer_ask_chat_refresh (window->buffer, 2); return 1; } - ptr_line = gui_chat_get_next_line_displayed (ptr_line); + ptr_line = gui_line_get_next_displayed (ptr_line); } } } @@ -997,7 +997,7 @@ gui_window_add_to_infolist (struct t_infolist *infolist, if (!infolist_new_var_integer (ptr_item, "start_line_y", ((window->buffer->type == GUI_BUFFER_TYPE_FREE) && (window->start_line)) ? - window->start_line->y : 0)) + window->start_line->data->y : 0)) return 0; return 1; |