diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c index 28d3b8520..d7dec68d8 100644 --- a/src/gui/curses/gui-curses-chat.c +++ b/src/gui/curses/gui-curses-chat.c @@ -487,6 +487,80 @@ gui_chat_display_word_raw (struct t_gui_window *window, struct t_gui_line *line, return chars_displayed; } +/* + * Displays the prefix_suffix in the beginning of a line. + * + * Returns number of chars displayed on screen. + */ + +int +gui_chat_display_prefix_suffix (struct t_gui_window *window, + struct t_gui_line *line, + const char *word, + int pre_lines_displayed, int *lines_displayed, + int simulate, + int apply_style_inactive, + int nick_offline) +{ + char str_space[] = " "; + int chars_displayed, length_align; + + chars_displayed = 0; + + /* insert spaces for aligning text under time/nick */ + length_align = gui_line_get_align (window->buffer, line, 0, 0); + + /* in the beginning of a line */ + if ((window->win_chat_cursor_x == 0) + && (*lines_displayed > pre_lines_displayed) + /* FIXME: modify arbitrary value for non aligning messages on time/nick? */ + && (length_align < (window->win_chat_width - 5))) + { + /* in the beginning of a word or in the middle of a word with multiline word align */ + if ((chars_displayed == 0) + || CONFIG_BOOLEAN(config_look_align_multiline_words)) + { + window->win_chat_cursor_x += length_align; + + if ((CONFIG_INTEGER(config_look_align_end_of_lines) == CONFIG_LOOK_ALIGN_END_OF_LINES_MESSAGE) + && (CONFIG_INTEGER(config_look_prefix_align) != CONFIG_LOOK_PREFIX_ALIGN_NONE) + && CONFIG_STRING(config_look_prefix_suffix) + && CONFIG_STRING(config_look_prefix_suffix)[0] + && line->data->date > 0) + { + if (!simulate) + { + gui_window_save_style (GUI_WINDOW_OBJECTS(window)->win_chat); + gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, + GUI_COLOR_CHAT_PREFIX_SUFFIX); + gui_window_current_emphasis = 0; + } + chars_displayed += gui_chat_display_word_raw (window, line, + CONFIG_STRING(config_look_prefix_suffix), + 0, simulate, + apply_style_inactive, + nick_offline); + window->win_chat_cursor_x += gui_chat_strlen_screen (CONFIG_STRING(config_look_prefix_suffix)); + chars_displayed += gui_chat_display_word_raw (window, line, + str_space, + 0, simulate, + apply_style_inactive, + nick_offline); + window->win_chat_cursor_x += gui_chat_strlen_screen (str_space); + if (!simulate) + gui_window_restore_style (GUI_WINDOW_OBJECTS(window)->win_chat); + } + } + if (!simulate && (window->win_chat_cursor_y < window->coords_size)) + { + window->coords[window->win_chat_cursor_y].line = line; + window->coords[window->win_chat_cursor_y].data = (char *)word; + } + } + + return chars_displayed; +} + /* * Displays a word on chat buffer. * @@ -503,9 +577,8 @@ gui_chat_display_word (struct t_gui_window *window, int apply_style_inactive, int nick_offline) { - char *data, *ptr_data, *end_line, saved_char, str_space[] = " "; + char *data, *ptr_data, *end_line, saved_char; int chars_displayed, pos_saved_char, chars_to_display, num_displayed; - int length_align; chars_displayed = 0; @@ -530,56 +603,13 @@ gui_chat_display_word (struct t_gui_window *window, ptr_data = data; while (ptr_data && ptr_data[0]) { - /* insert spaces for aligning text under time/nick */ - length_align = gui_line_get_align (window->buffer, line, 0, 0); - - /* in the beginning of a line */ - if ((window->win_chat_cursor_x == 0) - && (*lines_displayed > pre_lines_displayed) - /* FIXME: modify arbitrary value for non aligning messages on time/nick? */ - && (length_align < (window->win_chat_width - 5))) - { - /* in the beginning of a word or in the middle of a word with multiline word align */ - if ((chars_displayed == 0) - || CONFIG_BOOLEAN(config_look_align_multiline_words)) - { - window->win_chat_cursor_x += length_align; - - if ((CONFIG_INTEGER(config_look_align_end_of_lines) == CONFIG_LOOK_ALIGN_END_OF_LINES_MESSAGE) - && (CONFIG_INTEGER(config_look_prefix_align) != CONFIG_LOOK_PREFIX_ALIGN_NONE) - && CONFIG_STRING(config_look_prefix_suffix) - && CONFIG_STRING(config_look_prefix_suffix)[0] - && line->data->date > 0) - { - if (!simulate) - { - gui_window_save_style (GUI_WINDOW_OBJECTS(window)->win_chat); - gui_window_set_weechat_color (GUI_WINDOW_OBJECTS(window)->win_chat, - GUI_COLOR_CHAT_PREFIX_SUFFIX); - gui_window_current_emphasis = 0; - } - chars_displayed += gui_chat_display_word_raw (window, line, - CONFIG_STRING(config_look_prefix_suffix), - 0, simulate, - apply_style_inactive, - nick_offline); - window->win_chat_cursor_x += gui_chat_strlen_screen (CONFIG_STRING(config_look_prefix_suffix)); - chars_displayed += gui_chat_display_word_raw (window, line, - str_space, - 0, simulate, - apply_style_inactive, - nick_offline); - window->win_chat_cursor_x += gui_chat_strlen_screen (str_space); - if (!simulate) - gui_window_restore_style (GUI_WINDOW_OBJECTS(window)->win_chat); - } - } - if (!simulate && (window->win_chat_cursor_y < window->coords_size)) - { - window->coords[window->win_chat_cursor_y].line = line; - window->coords[window->win_chat_cursor_y].data = (char *)word + (ptr_data - data); - } - } + chars_displayed += gui_chat_display_prefix_suffix(window, line, + word + (ptr_data - data), + pre_lines_displayed, + lines_displayed, + simulate, + apply_style_inactive, + nick_offline); chars_to_display = gui_chat_strlen_screen (ptr_data); @@ -1352,7 +1382,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, int num_lines, x, y, pre_lines_displayed, lines_displayed, line_align; int read_marker_x, read_marker_y; int word_start_offset, word_end_offset; - int word_length_with_spaces, word_length; + int word_length_with_spaces, word_length, word_is_newlines; char *message_with_tags, *message_with_search; const char *ptr_data, *ptr_end_offset, *ptr_style, *next_char; struct t_gui_line *ptr_prev_line, *ptr_next_line; @@ -1492,7 +1522,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, ptr_data, &word_start_offset, &word_end_offset, - &word_length_with_spaces, &word_length); + &word_length_with_spaces, &word_length, &word_is_newlines); ptr_end_offset = ptr_data + word_end_offset; @@ -1505,43 +1535,68 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, if (word_length >= 0) { - line_align = gui_line_get_align (window->buffer, line, 1, - (lines_displayed == 0) ? 1 : 0); - 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)) + if (word_is_newlines) { - /* spaces + word too long for current line but OK for next line */ - gui_chat_display_new_line (window, num_lines, count, - &lines_displayed, simulate); - /* apply styles before jumping to start of word */ - if (!simulate && (word_start_offset > 0)) - { - ptr_style = ptr_data; - while (ptr_style < ptr_data + word_start_offset) - { - /* loop until no style/char available */ - ptr_style = gui_chat_string_next_char (window, line, - (unsigned char *)ptr_style, - 1, - CONFIG_BOOLEAN(config_look_color_inactive_message), - 0); - if (!ptr_style) - break; - ptr_style = utf8_next_char (ptr_style); - } - } /* jump to start of word */ ptr_data += word_start_offset; - } - /* display word */ - gui_chat_display_word (window, line, ptr_data, - ptr_end_offset + 1, - 0, num_lines, count, - pre_lines_displayed, &lines_displayed, - simulate, - CONFIG_BOOLEAN(config_look_color_inactive_message), - 0); + while (ptr_data && ptr_data[0] == '\n') + { + gui_chat_display_new_line (window, num_lines, count, + &lines_displayed, simulate); + ptr_data++; + gui_chat_display_prefix_suffix(window, line, + ptr_data, + pre_lines_displayed, &lines_displayed, + simulate, + CONFIG_BOOLEAN(config_look_color_inactive_message), + 0); + } + + if (!ptr_data[0]) + gui_chat_display_new_line (window, num_lines, count, + &lines_displayed, simulate); + } + else + { + line_align = gui_line_get_align (window->buffer, line, 1, + (lines_displayed == 0) ? 1 : 0); + 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)) + { + /* spaces + word too long for current line but OK for next line */ + gui_chat_display_new_line (window, num_lines, count, + &lines_displayed, simulate); + /* apply styles before jumping to start of word */ + if (!simulate && (word_start_offset > 0)) + { + ptr_style = ptr_data; + while (ptr_style < ptr_data + word_start_offset) + { + /* loop until no style/char available */ + ptr_style = gui_chat_string_next_char (window, line, + (unsigned char *)ptr_style, + 1, + CONFIG_BOOLEAN(config_look_color_inactive_message), + 0); + if (!ptr_style) + break; + ptr_style = utf8_next_char (ptr_style); + } + } + /* jump to start of word */ + ptr_data += word_start_offset; + } + + /* display word */ + gui_chat_display_word (window, line, ptr_data, + ptr_end_offset + 1, + 0, num_lines, count, + pre_lines_displayed, &lines_displayed, + simulate, + CONFIG_BOOLEAN(config_look_color_inactive_message), + 0); + } if ((!simulate) && (window->win_chat_cursor_y >= window->win_chat_height)) ptr_data = NULL; @@ -1552,7 +1607,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, if (*(ptr_data - 1) == '\0') ptr_data = NULL; - if (window->win_chat_cursor_x == 0) + if (window->win_chat_cursor_x == 0 && !word_is_newlines) { while (ptr_data && (ptr_data[0] == ' ')) { @@ -2107,8 +2162,8 @@ end: void gui_chat_draw_bare (struct t_gui_window *window) { - struct t_gui_line *ptr_line; - char *line; + struct t_gui_line *ptr_gui_line; + char *line, *ptr_line_start, *ptr_line_end; int y, length, num_lines; /* in bare display, we display ONLY the current window/buffer */ @@ -2126,53 +2181,117 @@ gui_chat_draw_bare (struct t_gui_window *window) y = 0; if (window->scroll->start_line) { - ptr_line = window->scroll->start_line; + ptr_gui_line = window->scroll->start_line; window->scroll->first_line_displayed = - (ptr_line == gui_line_get_first_displayed (window->buffer)); + (ptr_gui_line == gui_line_get_first_displayed (window->buffer)); } else { - ptr_line = gui_line_get_first_displayed (window->buffer); + ptr_gui_line = gui_line_get_first_displayed (window->buffer); window->scroll->first_line_displayed = 1; } - while (ptr_line && (y < gui_term_lines)) + while (ptr_gui_line && (y < gui_term_lines)) { - line = gui_chat_get_bare_line (ptr_line); + line = gui_chat_get_bare_line (ptr_gui_line); if (!line) break; - length = utf8_strlen_screen (line); - num_lines = length / gui_term_cols; - if (length % gui_term_cols != 0) - num_lines++; - if (y + num_lines <= gui_term_lines) - printf ("\033[%d;1H%s", y + 1, line); + + ptr_line_start = line; + ptr_line_end = line; + while (ptr_line_start) + { + ptr_line_end = strchr (ptr_line_start, '\n'); + if (ptr_line_end) + ptr_line_end[0] = '\0'; + + length = utf8_strlen_screen (ptr_line_start); + num_lines = length == 0 ? 1 : length / gui_term_cols; + if (length % gui_term_cols != 0) + num_lines++; + if (y + num_lines <= gui_term_lines) + printf ("\033[%d;1H%s", y + 1, ptr_line_start); + y += num_lines; + + if (ptr_line_end) + { + ptr_line_end[0] = '\n'; + ptr_line_start = ptr_line_end + 1; + } + else + { + ptr_line_start = NULL; + } + } + free (line); - y += num_lines; - ptr_line = gui_line_get_next_displayed (ptr_line); + ptr_gui_line = gui_line_get_next_displayed (ptr_gui_line); } } else { /* display from bottom to top (starting with last line of buffer) */ y = gui_term_lines; - ptr_line = gui_line_get_last_displayed (window->buffer); - while (ptr_line && (y >= 0)) + ptr_gui_line = gui_line_get_last_displayed (window->buffer); + while (ptr_gui_line && (y >= 0)) { - line = gui_chat_get_bare_line (ptr_line); + line = gui_chat_get_bare_line (ptr_gui_line); if (!line) break; - length = utf8_strlen_screen (line); - num_lines = length / gui_term_cols; - if (length % gui_term_cols != 0) - num_lines++; - y -= num_lines; + + ptr_line_start = line; + ptr_line_end = line; + while (ptr_line_start) + { + ptr_line_end = strchr (ptr_line_start, '\n'); + if (ptr_line_end) + ptr_line_end[0] = '\0'; + length = utf8_strlen_screen (ptr_line_start); + num_lines = length == 0 ? 1 : length / gui_term_cols; + if (length % gui_term_cols != 0) + num_lines++; + y -= num_lines; + if (ptr_line_end) + { + ptr_line_end[0] = '\n'; + ptr_line_start = ptr_line_end + 1; + } + else + { + ptr_line_start = NULL; + } + } + if (y >= 0) - printf ("\033[%d;1H%s", y + 1, line); + { + printf ("\033[%d;1H", y + 1); + ptr_line_start = line; + ptr_line_end = line; + while (ptr_line_start) + { + ptr_line_end = strchr (ptr_line_start, '\n'); + if (ptr_line_end) + ptr_line_end[0] = '\0'; + + printf ("%s", ptr_line_start); + + if (ptr_line_end) + { + printf ("\r\n"); + ptr_line_end[0] = '\n'; + ptr_line_start = ptr_line_end + 1; + } + else + { + ptr_line_start = NULL; + } + } + } + free (line); - ptr_line = gui_line_get_prev_displayed (ptr_line); + ptr_gui_line = gui_line_get_prev_displayed (ptr_gui_line); } window->scroll->first_line_displayed = - (ptr_line == gui_line_get_first_displayed (window->buffer)); + (ptr_gui_line == gui_line_get_first_displayed (window->buffer)); } /* diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c index 6841b95ff..e9b06a7a4 100644 --- a/src/gui/gui-chat.c +++ b/src/gui/gui-chat.c @@ -312,7 +312,8 @@ void gui_chat_get_word_info (struct t_gui_window *window, const char *data, int *word_start_offset, int *word_end_offset, - int *word_length_with_spaces, int *word_length) + int *word_length_with_spaces, int *word_length, + int *word_is_newlines) { const char *start_data, *next_char, *next_char2; int leading_spaces, char_size_screen; @@ -321,6 +322,7 @@ gui_chat_get_word_info (struct t_gui_window *window, *word_end_offset = 0; *word_length_with_spaces = 0; *word_length = -1; + *word_is_newlines = 0; start_data = data; @@ -334,8 +336,11 @@ gui_chat_get_word_info (struct t_gui_window *window, next_char2 = utf8_next_char (next_char); if (next_char2) { - if (next_char[0] != ' ') + if (next_char[0] != ' ' && + (leading_spaces || (next_char[0] == '\n') == *word_is_newlines)) { + if (next_char[0] == '\n') + *word_is_newlines = 1; if (leading_spaces) *word_start_offset = next_char - start_data; leading_spaces = 0; diff --git a/src/gui/gui-chat.h b/src/gui/gui-chat.h index 0971b93f9..28c222a69 100644 --- a/src/gui/gui-chat.h +++ b/src/gui/gui-chat.h @@ -83,7 +83,8 @@ extern void gui_chat_get_word_info (struct t_gui_window *window, const char *data, int *word_start_offset, int *word_end_offset, int *word_length_with_spaces, - int *word_length); + int *word_length, + int *word_is_newlines); extern char *gui_chat_get_time_string (time_t date); extern int gui_chat_get_time_length (); extern void gui_chat_change_time_format (); diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c index 6cb8fc007..8bd621cca 100644 --- a/src/gui/gui-window.c +++ b/src/gui/gui-window.c @@ -141,7 +141,7 @@ gui_window_get_context_at_xy (struct t_gui_window *window, { int win_x, win_y, coords_x_message; char *data_next_line, *str_temp; - const char *ptr_data, *word_start, *word_end, *last_space; + const char *ptr_data, *word_start, *word_end, *last_whitespace; *chat = 0; *line = NULL; @@ -227,9 +227,9 @@ gui_window_get_context_at_xy (struct t_gui_window *window, free (str_temp); } *end = gui_color_decode (ptr_data, NULL); - if (ptr_data[0] != ' ') + if (ptr_data[0] != ' ' && ptr_data[0] != '\n') { - last_space = NULL; + last_whitespace = NULL; word_start = (*line)->data->message; while (word_start && (word_start < ptr_data)) { @@ -238,12 +238,12 @@ gui_window_get_context_at_xy (struct t_gui_window *window, 0, 0, 0); if (word_start) { - if (word_start[0] == ' ') - last_space = word_start; + if (word_start[0] == ' ' || word_start[0] == '\n') + last_whitespace = word_start; word_start = utf8_next_char (word_start); } } - word_start = (last_space) ? last_space + 1 : (*line)->data->message; + word_start = (last_whitespace) ? last_whitespace + 1 : (*line)->data->message; word_end = ptr_data; while (word_end && word_end[0]) { @@ -252,7 +252,7 @@ gui_window_get_context_at_xy (struct t_gui_window *window, 0, 0, 0); if (word_end) { - if (word_end[0] == ' ') + if (word_end[0] == ' ' || word_end[0] == '\n') break; word_end = utf8_next_char (word_end); } diff --git a/tests/unit/gui/test-gui-chat.cpp b/tests/unit/gui/test-gui-chat.cpp index 96c93c4ed..99152886b 100644 --- a/tests/unit/gui/test-gui-chat.cpp +++ b/tests/unit/gui/test-gui-chat.cpp @@ -34,19 +34,23 @@ extern "C" #define WEE_GET_WORD_INFO(__result_word_start_offset, \ __result_word_end_offset, \ __result_word_length_with_spaces, \ - __result_word_length, __string) \ + __result_word_length, \ + __result_word_is_newlines, __string) \ word_start_offset = -2; \ word_end_offset = -2; \ word_length_with_spaces = -2; \ word_length = -2; \ + word_is_newlines = -2; \ gui_chat_get_word_info (gui_windows, __string, \ &word_start_offset, &word_end_offset, \ - &word_length_with_spaces, &word_length); \ + &word_length_with_spaces, &word_length, \ + &word_is_newlines); \ LONGS_EQUAL(__result_word_start_offset, word_start_offset); \ LONGS_EQUAL(__result_word_end_offset, word_end_offset); \ LONGS_EQUAL(__result_word_length_with_spaces, \ word_length_with_spaces); \ - LONGS_EQUAL(__result_word_length, word_length); + LONGS_EQUAL(__result_word_length, word_length); \ + LONGS_EQUAL(__result_word_is_newlines, word_is_newlines); TEST_GROUP(GuiChat) { @@ -334,16 +338,19 @@ TEST(GuiChat, StringPos) TEST(GuiChat, GetWordInfo) { int word_start_offset, word_end_offset, word_length_with_spaces; - int word_length; + int word_length, word_is_newlines; - WEE_GET_WORD_INFO (0, 0, 0, -1, NULL); - WEE_GET_WORD_INFO (0, 0, 0, -1, ""); - WEE_GET_WORD_INFO (0, 0, 1, 1, "a"); - WEE_GET_WORD_INFO (0, 2, 3, 3, "abc"); - WEE_GET_WORD_INFO (2, 4, 5, 3, " abc"); - WEE_GET_WORD_INFO (2, 4, 5, 3, " abc "); - WEE_GET_WORD_INFO (0, 4, 5, 5, "first second"); - WEE_GET_WORD_INFO (1, 5, 6, 5, " first second"); + WEE_GET_WORD_INFO (0, 0, 0, -1, 0, NULL); + WEE_GET_WORD_INFO (0, 0, 0, -1, 0, ""); + WEE_GET_WORD_INFO (0, 0, 1, 1, 0, "a"); + WEE_GET_WORD_INFO (0, 2, 3, 3, 0, "abc"); + WEE_GET_WORD_INFO (2, 4, 5, 3, 0, " abc"); + WEE_GET_WORD_INFO (2, 4, 5, 3, 0, " abc "); + WEE_GET_WORD_INFO (0, 4, 5, 5, 0, "first second"); + WEE_GET_WORD_INFO (1, 5, 6, 5, 0, " first second"); + WEE_GET_WORD_INFO (0, 0, 1, 1, 1, "\nabc"); + WEE_GET_WORD_INFO (2, 2, 3, 1, 1, " \nabc"); + WEE_GET_WORD_INFO (2, 3, 4, 2, 1, " \n\nabc"); } /*