int gui_chat_string_real_pos (const char *string, int pos) { const char *real_pos, *ptr_string; int size_on_screen; if (pos <= 0) return 0; real_pos = string; ptr_string = string; while (ptr_string && ptr_string[0] && (pos > 0)) { ptr_string = gui_chat_string_next_char (NULL, (unsigned char *)ptr_string, 0); if (ptr_string) { size_on_screen = (((unsigned char)ptr_string[0]) < 32) ? 1 : utf8_char_size_screen (ptr_string); if (size_on_screen > 0) pos -= size_on_screen; ptr_string = utf8_next_char (ptr_string); real_pos = ptr_string; } } return 0 + (real_pos - string); }
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")); }
int gui_chat_char_size_screen (const char *utf_char) { /* if char is invalid, it will be displayed as one space on screen */ if (!gui_chat_utf_char_valid (utf_char)) return 1; return utf8_char_size_screen (utf_char); }
int gui_chat_strlen_screen (const char *string) { int length, size_on_screen; length = 0; while (string && string[0]) { string = gui_chat_string_next_char (NULL, (unsigned char *)string, 0); if (string) { size_on_screen = (((unsigned char)string[0]) < 32) ? 1 : utf8_char_size_screen (string); if (size_on_screen > 0) length += size_on_screen; string = utf8_next_char (string); } } return length; }
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)); }
int gui_bar_window_print_string (struct t_gui_bar_window *bar_window, enum t_gui_bar_filling filling, int *x, int *y, const char *string, int reset_color_before_display, int hide_chars_if_scrolling, int *index_item, int *index_subitem, int *index_line) { int x_with_hidden, size_on_screen, low_char, hidden; char utf_char[16], *next_char, *output; if (!string || !string[0]) return 1; wmove (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, *y, *x); if (reset_color_before_display) { 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])); } x_with_hidden = *x; hidden = 0; while (string && string[0]) { switch (string[0]) { case GUI_COLOR_COLOR_CHAR: string++; switch (string[0]) { case GUI_COLOR_FG_CHAR: /* fg color */ string++; gui_window_string_apply_color_fg ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_BG_CHAR: /* bg color */ string++; gui_window_string_apply_color_bg ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_FG_BG_CHAR: /* fg + bg color */ string++; gui_window_string_apply_color_fg_bg ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_EXTENDED_CHAR: /* pair number */ string++; gui_window_string_apply_color_pair ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_EMPHASIS_CHAR: /* emphasis */ string++; gui_window_toggle_emphasis (); break; case GUI_COLOR_BAR_CHAR: /* bar color */ switch (string[1]) { case GUI_COLOR_BAR_FG_CHAR: /* bar foreground */ string += 2; gui_window_set_custom_color_fg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG])); break; case GUI_COLOR_BAR_DELIM_CHAR: /* bar delimiter */ string += 2; gui_window_set_custom_color_fg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_DELIM])); break; case GUI_COLOR_BAR_BG_CHAR: /* bar background */ string += 2; gui_window_set_custom_color_bg (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG])); break; case GUI_COLOR_BAR_START_INPUT_CHAR: string += 2; hidden = 0; break; case GUI_COLOR_BAR_START_INPUT_HIDDEN_CHAR: string += 2; hidden = 1; break; case GUI_COLOR_BAR_MOVE_CURSOR_CHAR: /* move cursor to current position on screen */ string += 2; getyx (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, bar_window->cursor_y, bar_window->cursor_x); bar_window->cursor_x += bar_window->x; bar_window->cursor_y += bar_window->y; break; case GUI_COLOR_BAR_START_ITEM: string += 2; if (*index_item < 0) { *index_item = 0; *index_subitem = 0; } else { (*index_subitem)++; if (*index_subitem >= bar_window->items_subcount[*index_item]) { (*index_item)++; *index_subitem = 0; } } *index_line = 0; gui_bar_window_coords_add (bar_window, (*index_item >= bar_window->items_count) ? -1 : *index_item, (*index_item >= bar_window->items_count) ? -1 : *index_subitem, *index_line, *x + bar_window->x, *y + bar_window->y); break; case GUI_COLOR_BAR_START_LINE_ITEM: string += 2; (*index_line)++; gui_bar_window_coords_add (bar_window, *index_item, *index_subitem, *index_line, *x + bar_window->x, *y + bar_window->y); break; default: string++; break; } break; case GUI_COLOR_RESET_CHAR: /* reset color (keep attributes) */ string++; 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])); break; default: gui_window_string_apply_color_weechat ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; } break; case GUI_COLOR_SET_ATTR_CHAR: string++; gui_window_string_apply_color_set_attr ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_REMOVE_ATTR_CHAR: string++; gui_window_string_apply_color_remove_attr ((unsigned char **)&string, GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar); break; case GUI_COLOR_RESET_CHAR: string++; gui_window_remove_color_style (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, A_ALL_ATTR); 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])); break; default: next_char = utf8_next_char (string); if (!next_char) break; memcpy (utf_char, string, next_char - string); utf_char[next_char - string] = '\0'; if ((((unsigned char)utf_char[0]) < 32) && (!utf_char[1])) { low_char = 1; snprintf (utf_char, sizeof (utf_char), "%c", 'A' + ((unsigned char)utf_char[0]) - 1); } else { low_char = 0; if (!gui_chat_utf_char_valid (utf_char)) snprintf (utf_char, sizeof (utf_char), " "); } size_on_screen = utf8_char_size_screen (utf_char); if (size_on_screen >= 0) { if (hide_chars_if_scrolling && (x_with_hidden < bar_window->scroll_x)) { /* hidden char (before scroll_x value) */ x_with_hidden++; } else if (!hidden) { if (*x + size_on_screen > bar_window->width) { if (filling == GUI_BAR_FILLING_VERTICAL) return 1; if (*y >= bar_window->height - 1) return 0; *x = 0; (*y)++; wmove (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, *y, *x); } output = string_iconv_from_internal (NULL, utf_char); if (low_char) wattron (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, A_REVERSE); waddstr (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, (output) ? output : utf_char); if (low_char) wattroff (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, A_REVERSE); if (output) free (output); if (gui_window_current_emphasis) { gui_window_emphasize (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, *x, *y, size_on_screen); } *x += size_on_screen; } } string = next_char; break; } } return 1; }