int gui_nicklist_get_max_length (struct t_gui_buffer *buffer, struct t_gui_nick_group *group) { int length, max_length; struct t_gui_nick_group *ptr_group; struct t_gui_nick *ptr_nick; if (!buffer) return 0; max_length = 0; for (ptr_group = (group) ? group : buffer->nicklist_root; ptr_group; ptr_group = ptr_group->next_group) { if (buffer->nicklist_display_groups && ptr_group->visible) { length = utf8_strlen_screen (gui_nicklist_get_group_start (ptr_group->name)) + ptr_group->level - 1; if (length > max_length) max_length = length; } for (ptr_nick = ptr_group->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick) { if (ptr_nick->visible) { if (buffer->nicklist_display_groups) length = utf8_strlen_screen (ptr_nick->name) + ptr_group->level + 1; else length = utf8_strlen_screen (ptr_nick->name) + 1; if (length > max_length) max_length = length; } } if (ptr_group->children) { length = gui_nicklist_get_max_length (buffer, ptr_group->children); if (length > max_length) max_length = length; } } return max_length; }
int utf8_char_size_screen (const char *string) { int char_size; char utf_char[16]; if (!string) return 0; char_size = utf8_char_size (string); if (char_size == 0) return 0; memcpy (utf_char, string, char_size); utf_char[char_size] = '\0'; return utf8_strlen_screen (utf_char); }
TEST(CoreUtf8, Size) { /* char size */ LONGS_EQUAL(0, utf8_char_size (NULL)); LONGS_EQUAL(1, utf8_char_size ("")); LONGS_EQUAL(1, utf8_char_size ("A")); LONGS_EQUAL(2, utf8_char_size ("ë")); LONGS_EQUAL(3, utf8_char_size ("€")); LONGS_EQUAL(3, utf8_char_size (cjk_yellow)); LONGS_EQUAL(4, utf8_char_size (han_char)); /* char size on screen */ LONGS_EQUAL(0, utf8_char_size_screen (NULL)); LONGS_EQUAL(0, utf8_char_size_screen ("")); LONGS_EQUAL(1, utf8_char_size_screen ("A")); LONGS_EQUAL(1, utf8_char_size_screen ("ë")); LONGS_EQUAL(1, utf8_char_size_screen ("€")); LONGS_EQUAL(2, utf8_char_size_screen (cjk_yellow)); /* length of string (in chars) */ LONGS_EQUAL(0, utf8_strlen (NULL)); LONGS_EQUAL(0, utf8_strlen ("")); LONGS_EQUAL(1, utf8_strlen ("A")); LONGS_EQUAL(1, utf8_strlen ("ë")); LONGS_EQUAL(1, utf8_strlen ("€")); LONGS_EQUAL(1, utf8_strlen (cjk_yellow)); LONGS_EQUAL(1, utf8_strlen (han_char)); /* length of string (in chars, for max N bytes) */ LONGS_EQUAL(0, utf8_strnlen (NULL, 0)); LONGS_EQUAL(0, utf8_strnlen ("", 0)); LONGS_EQUAL(1, utf8_strnlen ("AZ", 1)); LONGS_EQUAL(1, utf8_strnlen ("ëZ", 2)); LONGS_EQUAL(1, utf8_strnlen ("€Z", 3)); LONGS_EQUAL(1, utf8_strnlen (han_char_z, 4)); /* length of string on screen (in chars) */ LONGS_EQUAL(0, utf8_strlen_screen (NULL)); LONGS_EQUAL(0, utf8_strlen_screen ("")); LONGS_EQUAL(1, utf8_strlen_screen ("A")); LONGS_EQUAL(1, utf8_strlen_screen ("ë")); LONGS_EQUAL(1, utf8_strlen_screen ("€")); LONGS_EQUAL(1, utf8_strlen_screen ("\x7f")); LONGS_EQUAL(2, utf8_strlen_screen (cjk_yellow)); }
TEST(Utf8, Size) { /* char size */ LONGS_EQUAL(0, utf8_char_size (NULL)); LONGS_EQUAL(1, utf8_char_size ("")); LONGS_EQUAL(1, utf8_char_size ("A")); LONGS_EQUAL(2, utf8_char_size ("ë")); LONGS_EQUAL(3, utf8_char_size ("€")); LONGS_EQUAL(4, utf8_char_size (han_char)); /* char size on screen */ LONGS_EQUAL(0, utf8_char_size_screen (NULL)); LONGS_EQUAL(0, utf8_char_size_screen ("")); LONGS_EQUAL(1, utf8_char_size_screen ("A")); LONGS_EQUAL(1, utf8_char_size_screen ("ë")); LONGS_EQUAL(1, utf8_char_size_screen ("€")); /* this test does not work on Ubuntu Precise: it returns 2 instead of 1 */ /*LONGS_EQUAL(1, utf8_char_size_screen (han_char));*/ /* length of string (in chars) */ LONGS_EQUAL(0, utf8_strlen (NULL)); LONGS_EQUAL(0, utf8_strlen ("")); LONGS_EQUAL(1, utf8_strlen ("A")); LONGS_EQUAL(1, utf8_strlen ("ë")); LONGS_EQUAL(1, utf8_strlen ("€")); LONGS_EQUAL(1, utf8_strlen (han_char)); /* length of string (in chars, for max N bytes) */ LONGS_EQUAL(0, utf8_strnlen (NULL, 0)); LONGS_EQUAL(0, utf8_strnlen ("", 0)); LONGS_EQUAL(1, utf8_strnlen ("AZ", 1)); LONGS_EQUAL(1, utf8_strnlen ("ëZ", 2)); LONGS_EQUAL(1, utf8_strnlen ("€Z", 3)); LONGS_EQUAL(1, utf8_strnlen (han_char_z, 4)); /* length of string on screen (in chars) */ LONGS_EQUAL(0, utf8_strlen_screen (NULL)); LONGS_EQUAL(0, utf8_strlen_screen ("")); LONGS_EQUAL(1, utf8_strlen_screen ("A")); LONGS_EQUAL(1, utf8_strlen_screen ("ë")); LONGS_EQUAL(1, utf8_strlen_screen ("€")); /* this test does not work on Ubuntu Precise: it returns 2 instead of 1 */ /*LONGS_EQUAL(1, utf8_strlen_screen (han_char));*/ LONGS_EQUAL(1, utf8_strlen_screen ("\x7f")); }
void gui_bar_window_draw (struct t_gui_bar_window *bar_window, struct t_gui_window *window) { int x, y, items_count, num_lines, line; enum t_gui_bar_filling filling; char *content, **items; static char str_start_input[16] = { '\0' }; static char str_start_input_hidden[16] = { '\0' }; static char str_cursor[16] = { '\0' }; char *pos_start_input, *pos_after_start_input, *pos_cursor, *buf; char *new_start_input, *ptr_string; static int length_start_input, length_start_input_hidden; int length_on_screen; int chars_available, index, size; int length_screen_before_cursor, length_screen_after_cursor; int diff, max_length, optimal_number_of_lines; int some_data_not_displayed; int index_item, index_subitem, index_line; if (!gui_init_ok) return; if (gui_window_bare_display) return; if ((bar_window->x < 0) || (bar_window->y < 0)) return; if (!str_start_input[0]) { snprintf (str_start_input, sizeof (str_start_input), "%c%c%c", GUI_COLOR_COLOR_CHAR, GUI_COLOR_BAR_CHAR, GUI_COLOR_BAR_START_INPUT_CHAR); length_start_input = strlen (str_start_input); snprintf (str_start_input_hidden, sizeof (str_start_input_hidden), "%c%c%c", GUI_COLOR_COLOR_CHAR, GUI_COLOR_BAR_CHAR, GUI_COLOR_BAR_START_INPUT_HIDDEN_CHAR); length_start_input_hidden = strlen (str_start_input_hidden); snprintf (str_cursor, sizeof (str_cursor), "%c%c%c", GUI_COLOR_COLOR_CHAR, GUI_COLOR_BAR_CHAR, GUI_COLOR_BAR_MOVE_CURSOR_CHAR); } /* * these values will be overwritten later (by gui_bar_window_print_string) * if cursor has to move somewhere in bar window */ bar_window->cursor_x = -1; bar_window->cursor_y = -1; /* remove coords */ gui_bar_window_coords_free (bar_window); index_item = -1; index_subitem = -1; index_line = 0; gui_window_current_emphasis = 0; filling = gui_bar_get_filling (bar_window->bar); content = gui_bar_window_content_get_with_filling (bar_window, window); if (content) { if ((filling == GUI_BAR_FILLING_HORIZONTAL) && (bar_window->scroll_x > 0)) { length_on_screen = gui_chat_strlen_screen (content); if (bar_window->scroll_x > length_on_screen - bar_window->width) { bar_window->scroll_x = length_on_screen - bar_window->width; if (bar_window->scroll_x < 0) bar_window->scroll_x = 0; } } items = string_split (content, "\n", 0, 0, &items_count); if (items_count == 0) { if (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_SIZE]) == 0) gui_bar_window_set_current_size (bar_window, window, 1); gui_window_clear (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG]), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); } else { /* bar with auto size ? then compute new size, according to content */ if (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_SIZE]) == 0) { /* search longer line and optimal number of lines */ max_length = 0; optimal_number_of_lines = 0; for (line = 0; line < items_count; line++) { length_on_screen = gui_chat_strlen_screen (items[line]); pos_cursor = strstr (items[line], str_cursor); if (pos_cursor && (gui_chat_strlen_screen (pos_cursor) == 0)) length_on_screen++; if (length_on_screen > max_length) max_length = length_on_screen; if (length_on_screen % bar_window->width == 0) num_lines = length_on_screen / bar_window->width; else num_lines = (length_on_screen / bar_window->width) + 1; if (num_lines == 0) num_lines = 1; optimal_number_of_lines += num_lines; } if (max_length == 0) max_length = 1; switch (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_POSITION])) { case GUI_BAR_POSITION_BOTTOM: case GUI_BAR_POSITION_TOP: if (filling == GUI_BAR_FILLING_HORIZONTAL) num_lines = optimal_number_of_lines; else num_lines = items_count; gui_bar_window_set_current_size (bar_window, window, num_lines); break; case GUI_BAR_POSITION_LEFT: case GUI_BAR_POSITION_RIGHT: gui_bar_window_set_current_size (bar_window, window, max_length); break; case GUI_BAR_NUM_POSITIONS: break; } } gui_window_clear (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG]), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); x = 0; y = 0; some_data_not_displayed = 0; if ((bar_window->scroll_y > 0) && (bar_window->scroll_y > items_count - bar_window->height)) { bar_window->scroll_y = items_count - bar_window->height; if (bar_window->scroll_y < 0) bar_window->scroll_y = 0; } for (line = 0; (line < items_count) && (y < bar_window->height); line++) { pos_start_input = strstr (items[line], str_start_input); if (pos_start_input) { pos_after_start_input = pos_start_input + strlen (str_start_input); pos_cursor = strstr (pos_after_start_input, str_cursor); if (pos_cursor) { chars_available = ((bar_window->height - y - 1) * bar_window->width) + /* next lines */ (bar_window->width - x - 1); /* chars on current line */ length_screen_before_cursor = -1; length_screen_after_cursor = -1; buf = string_strndup (items[line], pos_cursor - items[line]); if (buf) { length_screen_before_cursor = gui_chat_strlen_screen (buf); length_screen_after_cursor = gui_chat_strlen_screen (pos_cursor); free (buf); } if ((length_screen_before_cursor < 0) || (length_screen_after_cursor < 0)) length_screen_before_cursor = gui_chat_strlen_screen (items[line]); diff = length_screen_before_cursor - chars_available; if (diff > 0) { if (CONFIG_INTEGER(config_look_input_cursor_scroll) > 0) { diff += (CONFIG_INTEGER(config_look_input_cursor_scroll) - 1 - (diff % CONFIG_INTEGER(config_look_input_cursor_scroll))); } /* compute new start for displaying input */ new_start_input = pos_after_start_input + gui_chat_string_real_pos (pos_after_start_input, diff, 1); if (new_start_input > pos_cursor) new_start_input = pos_cursor; buf = malloc (strlen (items[line]) + length_start_input_hidden + 1); if (buf) { /* add string before start of input */ index = 0; if (pos_start_input > items[line]) { size = pos_start_input - items[line]; memmove (buf, items[line], size); index += size; } /* add tag "start_input_hidden" */ memmove (buf + index, str_start_input_hidden, length_start_input_hidden); index += length_start_input_hidden; /* add hidden part of input */ size = new_start_input - pos_after_start_input; memmove (buf + index, pos_after_start_input, size); index += size; /* add tag "start_input" */ memmove (buf + index, str_start_input, length_start_input); index += length_start_input; /* add input (will be displayed) */ size = strlen (new_start_input) + 1; memmove (buf + index, new_start_input, size); free (items[line]); items[line] = buf; } } } } if ((bar_window->scroll_y == 0) || (line >= bar_window->scroll_y)) { if (!gui_bar_window_print_string (bar_window, filling, &x, &y, items[line], 1, 1, &index_item, &index_subitem, &index_line)) { some_data_not_displayed = 1; } if (x < bar_window->width) { if (filling == GUI_BAR_FILLING_HORIZONTAL) { gui_window_set_custom_color_fg_bg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG]), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); gui_window_remove_color_style (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, A_ALL_ATTR); wclrtobot (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); } else { gui_window_remove_color_style (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, A_ALL_ATTR); } while (x < bar_window->width) { gui_bar_window_print_string (bar_window, filling, &x, &y, " ", 0, 0, &index_item, &index_subitem, &index_line); } } x = 0; y++; } } if ((bar_window->cursor_x < 0) && (bar_window->cursor_y < 0) && ((bar_window->scroll_x > 0) || (bar_window->scroll_y > 0))) { if (filling == GUI_BAR_FILLING_HORIZONTAL) { ptr_string = CONFIG_STRING(config_look_bar_more_left); x = 0; } else { ptr_string = CONFIG_STRING(config_look_bar_more_up); x = bar_window->width - utf8_strlen_screen (ptr_string); if (x < 0) x = 0; } y = 0; if (ptr_string && ptr_string[0]) { gui_window_set_custom_color_fg_bg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(config_color_bar_more), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); mvwaddstr (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, y, x, ptr_string); } } if ((bar_window->cursor_x < 0) && (bar_window->cursor_y < 0) && (some_data_not_displayed || (line < items_count))) { ptr_string = (filling == GUI_BAR_FILLING_HORIZONTAL) ? CONFIG_STRING(config_look_bar_more_right) : CONFIG_STRING(config_look_bar_more_down); x = bar_window->width - utf8_strlen_screen (ptr_string); if (x < 0) x = 0; y = (bar_window->height > 1) ? bar_window->height - 1 : 0; if (ptr_string && ptr_string[0]) { gui_window_set_custom_color_fg_bg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(config_color_bar_more), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); mvwaddstr (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, y, x, ptr_string); } } } if (items) string_free_split (items); free (content); } else { if (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_SIZE]) == 0) gui_bar_window_set_current_size (bar_window, window, 1); gui_window_clear (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG]), CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); } /* * move cursor if it was asked in an item content (input_text does that * to move cursor in user input text) */ if ((!window || (gui_current_window == window)) && (bar_window->cursor_x >= 0) && (bar_window->cursor_y >= 0)) { y = bar_window->cursor_y - bar_window->y; x = bar_window->cursor_x - bar_window->x; if (x > bar_window->width - 2) x = bar_window->width - 2; wmove (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, y, x); wrefresh (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); if (!gui_cursor_mode) { gui_window_cursor_x = bar_window->cursor_x; gui_window_cursor_y = bar_window->cursor_y; move (bar_window->cursor_y, bar_window->cursor_x); } } else wnoutrefresh (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); if (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_SEPARATOR])) { switch (CONFIG_INTEGER(bar_window->bar->options[GUI_BAR_OPTION_POSITION])) { case GUI_BAR_POSITION_BOTTOM: gui_window_set_weechat_color (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, GUI_COLOR_SEPARATOR); gui_window_hline (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, 0, 0, bar_window->width, CONFIG_STRING(config_look_separator_horizontal)); break; case GUI_BAR_POSITION_TOP: gui_window_set_weechat_color (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, GUI_COLOR_SEPARATOR); gui_window_hline (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, 0, 0, bar_window->width, CONFIG_STRING(config_look_separator_horizontal)); break; case GUI_BAR_POSITION_LEFT: gui_window_set_weechat_color (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, GUI_COLOR_SEPARATOR); gui_window_vline (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, 0, 0, bar_window->height, CONFIG_STRING(config_look_separator_vertical)); break; case GUI_BAR_POSITION_RIGHT: gui_window_set_weechat_color (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, GUI_COLOR_SEPARATOR); gui_window_vline (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator, 0, 0, bar_window->height, CONFIG_STRING(config_look_separator_vertical)); break; case GUI_BAR_NUM_POSITIONS: break; } wnoutrefresh (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_separator); } refresh (); }