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 (); }
char * gui_color_emphasize (const char *string, const char *search, int case_sensitive, regex_t *regex) { regmatch_t regex_match; char *result, *result2, *string_no_color, *pos; const char *ptr_string, *ptr_no_color, *color_emphasis; int rc, length_search, length_emphasis, length_result; int pos1, pos2, real_pos1, real_pos2, count_emphasis; if (!string && !regex) return NULL; color_emphasis = gui_color_get_custom ("emphasis"); if (!color_emphasis) return NULL; length_emphasis = strlen (color_emphasis); /* * allocate space for 8 emphasized strings (8 before + 8 after = 16); * more space will be allocated later (if there are more than 8 emphasized * strings) */ length_result = strlen (string) + (length_emphasis * 2 * 8) + 1; result = malloc (length_result); if (!result) return NULL; result[0] = '\0'; /* * build a string without color codes to search in this one (then with the * position of text found, we will retrieve position in original string, * which can contain color codes) */ string_no_color = gui_color_decode (string, NULL); if (!string_no_color) { free (result); return NULL; } length_search = (search) ? strlen (search) : 0; ptr_string = string; ptr_no_color = string_no_color; count_emphasis = 0; while (ptr_no_color && ptr_no_color[0]) { if (regex) { /* search next match using the regex */ regex_match.rm_so = -1; rc = regexec (regex, ptr_no_color, 1, ®ex_match, 0); /* * no match found: exit the loop (if rm_no == 0, it is an empty * match at beginning of string: we consider there is no match, to * prevent an infinite loop) */ if ((rc != 0) || (regex_match.rm_so < 0) || (regex_match.rm_eo <= 0)) { strcat (result, ptr_string); break; } pos1 = regex_match.rm_so; pos2 = regex_match.rm_eo; } else { /* search next match in the string */ if (case_sensitive) pos = strstr (ptr_no_color, search); else pos = string_strcasestr (ptr_no_color, search); if (!pos) { strcat (result, ptr_string); break; } pos1 = pos - ptr_no_color; pos2 = pos1 + length_search; if (pos2 <= 0) { strcat (result, ptr_string); break; } } /* * find the position of match in the original string (which can contain * color codes) */ real_pos1 = gui_chat_string_real_pos (ptr_string, gui_chat_string_pos (ptr_no_color, pos1)); real_pos2 = gui_chat_string_real_pos (ptr_string, gui_chat_string_pos (ptr_no_color, pos2)); /* * concatenate following strings to the result: * - beginning of string (before match) * - emphasis color code * - the matching string * - emphasis color code */ if (real_pos1 > 0) strncat (result, ptr_string, real_pos1); strcat (result, color_emphasis); strncat (result, ptr_string + real_pos1, real_pos2 - real_pos1); strcat (result, color_emphasis); /* restart next loop after the matching string */ ptr_string += real_pos2; ptr_no_color += pos2; /* check if we should allocate more space for emphasis color codes */ count_emphasis++; if (count_emphasis == 8) { /* allocate more space for emphasis color codes */ length_result += (length_emphasis * 2 * 8); result2 = realloc (result, length_result); if (!result2) { free (result); return NULL; } result = result2; count_emphasis = 0; } } free (string_no_color); return result; }