/* * Copyright (C) 2003-2011 Sebastien Helleu * * This file is part of WeeChat, the extensible chat client. * * WeeChat 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. * * WeeChat 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 WeeChat. If not, see . */ /* * gui-curses-color.c: color functions for Curses GUI */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "../../core/weechat.h" #include "../../core/wee-config.h" #include "../../core/wee-hashtable.h" #include "../../core/wee-hook.h" #include "../../core/wee-list.h" #include "../../core/wee-string.h" #include "../../core/wee-utf8.h" #include "../../plugins/plugin.h" #include "../gui-buffer.h" #include "../gui-color.h" #include "../gui-chat.h" #include "../gui-window.h" #include "gui-curses.h" #define GUI_COLOR_TIMER_TERM_COLORS 10 struct t_gui_color gui_weechat_colors[GUI_CURSES_NUM_WEECHAT_COLORS + 1] = { { -1, -1, 0, "default" }, { COLOR_BLACK, COLOR_BLACK, 0, "black" }, { COLOR_BLACK, COLOR_BLACK + 8, A_BOLD, "darkgray" }, { COLOR_RED, COLOR_RED, 0, "red" }, { COLOR_RED, COLOR_RED + 8, A_BOLD, "lightred" }, { COLOR_GREEN, COLOR_GREEN, 0, "green" }, { COLOR_GREEN, COLOR_GREEN + 8, A_BOLD, "lightgreen" }, { COLOR_YELLOW, COLOR_YELLOW, 0, "brown" }, { COLOR_YELLOW, COLOR_YELLOW + 8, A_BOLD, "yellow" }, { COLOR_BLUE, COLOR_BLUE, 0, "blue" }, { COLOR_BLUE, COLOR_BLUE + 8, A_BOLD, "lightblue" }, { COLOR_MAGENTA, COLOR_MAGENTA, 0, "magenta" }, { COLOR_MAGENTA, COLOR_MAGENTA + 8, A_BOLD, "lightmagenta" }, { COLOR_CYAN, COLOR_CYAN, 0, "cyan" }, { COLOR_CYAN, COLOR_CYAN + 8, A_BOLD, "lightcyan" }, { COLOR_WHITE, COLOR_WHITE, 0, "gray" }, { COLOR_WHITE, COLOR_WHITE + 8, A_BOLD, "white" }, { 0, 0, 0, NULL } }; /* terminal colors */ int gui_color_term_has_colors = 0; /* terminal supports colors? */ int gui_color_term_colors = 0; /* number of colors in terminal */ int gui_color_term_color_pairs = 0; /* number of pairs in terminal */ int gui_color_term_can_change_color = 0; /* change color allowed in term? */ int gui_color_use_term_colors = 0; /* temp. use of terminal colors? */ short *gui_color_term_color_content = NULL; /* content of colors (r/b/g) */ /* pairs */ int gui_color_num_pairs = 63; /* number of pairs used by WeeChat */ short *gui_color_pairs = NULL; /* table with pair for each fg+bg */ int gui_color_pairs_used = 0; /* number of pairs currently used */ int gui_color_warning_pairs_full = 0; /* warning displayed? */ /* color buffer */ struct t_gui_buffer *gui_color_buffer = NULL; /* buffer with colors */ int gui_color_buffer_extra_info = 0; /* display extra info? */ int gui_color_buffer_refresh_needed = 0; /* refresh needed on buffer? */ struct t_hook *gui_color_hook_timer = NULL; /* timer for terminal colors */ int gui_color_timer = 0; /* timer in seconds */ /* * gui_color_search: search a color by name * Return: number of color in WeeChat colors table */ int gui_color_search (const char *color_name) { int i; for (i = 0; gui_weechat_colors[i].string; i++) { if (string_strcasecmp (gui_weechat_colors[i].string, color_name) == 0) return i; } /* color not found */ return -1; } /* * gui_color_assign: assign a WeeChat color (read from config) * return 1 if ok, 0 if error */ int gui_color_assign (int *color, const char *color_name) { int flag, extra_attr, color_index, number; char *error; /* read extended attributes */ extra_attr = 0; while ((flag = gui_color_attr_get_flag (color_name[0])) > 0) { extra_attr |= flag; color_name++; } /* is it a color alias? */ number = gui_color_palette_get_alias (color_name); if (number >= 0) { *color = number | GUI_COLOR_EXTENDED_FLAG | extra_attr; return 1; } /* is it a color number? */ error = NULL; number = (int)strtol (color_name, &error, 10); if (color_name[0] && error && !error[0] && (number >= 0)) { /* color_name is a number, use this color number */ if (number > GUI_COLOR_EXTENDED_MAX) number = GUI_COLOR_EXTENDED_MAX; *color = number | GUI_COLOR_EXTENDED_FLAG | extra_attr; return 1; } else { /* search for basic WeeChat color */ color_index = gui_color_search (color_name); if (color_index >= 0) { *color = color_index | extra_attr; return 1; } } /* color not found */ return 0; } /* * gui_color_assign_by_diff: assign color by difference * It is called when a color option is * set with value ++X or --X, to search * another color (for example ++1 is * next color/alias in list) * return 1 if ok, 0 if error */ int gui_color_assign_by_diff (int *color, const char *color_name, int diff) { int index, list_size; struct t_weelist_item *ptr_item; const char *name; index = weelist_search_pos (gui_color_list_with_alias, color_name); if (index < 0) index = 0; list_size = weelist_size (gui_color_list_with_alias); diff = diff % (list_size + 1); if (diff > 0) { index = (index + diff) % (list_size + 1); while (index > list_size - 1) { index -= list_size; } } else { index = (index + list_size + diff) % list_size; while (index < 0) { index += list_size; } } ptr_item = weelist_get (gui_color_list_with_alias, index); if (!ptr_item) return 0; name = weelist_string (ptr_item); if (name) return gui_color_assign (color, name); return 0; } /* * gui_color_get_weechat_colors_number: get number of WeeChat colors */ int gui_color_get_weechat_colors_number () { return GUI_CURSES_NUM_WEECHAT_COLORS; } /* * gui_color_get_term_colors: get number of colors supported by terminal */ int gui_color_get_term_colors () { return gui_color_term_colors; } /* * gui_color_get_pairs_arrays: get current pairs as arrays (one array for * foregrounds, another for backgrounds) * Each array has "gui_color_num_pairs+1" entries. * Pairs not used have value -2 in both arrays. */ void gui_color_get_pairs_arrays (short **foregrounds, short **backgrounds) { int i, fg, bg, index; if (!foregrounds || !backgrounds) return; *foregrounds = NULL; *backgrounds = NULL; *foregrounds = malloc (sizeof (*foregrounds[0]) * (gui_color_num_pairs + 1)); if (!*foregrounds) goto error; *backgrounds = malloc (sizeof (*backgrounds[0]) * (gui_color_num_pairs + 1)); if (!*backgrounds) goto error; for (i = 0; i <= gui_color_num_pairs; i++) { (*foregrounds)[i] = -2; (*backgrounds)[i] = -2; } for (bg = -1; bg <= gui_color_term_colors; bg++) { for (fg = -1; fg <= gui_color_term_colors; fg++) { index = ((bg + 1) * (gui_color_term_colors + 2)) + (fg + 1); if ((gui_color_pairs[index] >= 1) && (gui_color_pairs[index] <= gui_color_num_pairs)) { (*foregrounds)[gui_color_pairs[index]] = fg; (*backgrounds)[gui_color_pairs[index]] = bg; } } } return; error: if (*foregrounds) { free (*foregrounds); *foregrounds = NULL; } if (*backgrounds) { free (*backgrounds); *backgrounds = NULL; } } /* * gui_color_timer_warning_pairs_full: display a warning when no more pair is * available in table */ int gui_color_timer_warning_pairs_full (void *data, int remaining_calls) { /* make C compiler happy */ (void) data; (void) remaining_calls; gui_chat_printf (NULL, _("Warning: the %d color pairs are used, do " "\"/color reset\" to remove unused pairs"), gui_color_num_pairs); return WEECHAT_RC_OK; } /* * gui_color_get_pair: get a pair with given foreground/background colors * If no pair is found for fg/bg, a new pair is created * Value returned is between 0 and COLOR_PAIRS-1 */ int gui_color_get_pair (int fg, int bg) { int index; /* only one color when displaying terminal colors */ if (gui_color_use_term_colors) return COLOR_WHITE; /* if invalid color, use default fg/bg */ if (fg > gui_color_term_colors) fg = -1; if (bg > gui_color_term_colors) bg = -1; /* compute index for gui_color_pairs with foreground and background */ index = ((bg + 1) * (gui_color_term_colors + 2)) + (fg + 1); /* pair not allocated for this fg/bg? */ if (gui_color_pairs[index] == 0) { if (gui_color_pairs_used >= gui_color_num_pairs) { /* oh no, no more pair available! */ if (!gui_color_warning_pairs_full) { hook_timer (NULL, 1, 0, 1, &gui_color_timer_warning_pairs_full, NULL); gui_color_warning_pairs_full = 1; } return 1; } /* create a new pair if no pair exists for this fg/bg */ gui_color_pairs_used++; gui_color_pairs[index] = gui_color_pairs_used; init_pair (gui_color_pairs_used, fg, bg); gui_color_buffer_refresh_needed = 1; } return gui_color_pairs[index]; } /* * gui_color_weechat_get_pair: get color pair with a WeeChat color number */ int gui_color_weechat_get_pair (int weechat_color) { int fg, bg; if ((weechat_color < 0) || (weechat_color > GUI_COLOR_NUM_COLORS - 1)) { fg = -1; bg = -1; } else { fg = gui_color[weechat_color]->foreground; bg = gui_color[weechat_color]->background; if ((fg > 0) && (fg & GUI_COLOR_EXTENDED_FLAG)) fg &= GUI_COLOR_EXTENDED_MASK; if ((bg > 0) && (bg & GUI_COLOR_EXTENDED_FLAG)) bg &= GUI_COLOR_EXTENDED_MASK; } return gui_color_get_pair (fg, bg); } /* * gui_color_get_name: get color name */ const char * gui_color_get_name (int num_color) { static char color[16][64]; static int index_color = 0; char str_attr[8]; struct t_gui_color_palette *ptr_color_palette; /* init color string */ index_color = (index_color + 1) % 16; color[index_color][0] = '\0'; /* build string with extra-attributes */ gui_color_attr_build_string (num_color, str_attr); if (num_color & GUI_COLOR_EXTENDED_FLAG) { /* search alias */ ptr_color_palette = gui_color_palette_get (num_color & GUI_COLOR_EXTENDED_MASK); if (ptr_color_palette && ptr_color_palette->alias) { /* alias */ snprintf (color[index_color], sizeof (color[index_color]), "%s%s", str_attr, ptr_color_palette->alias); } else { /* color number */ snprintf (color[index_color], sizeof (color[index_color]), "%s%d", str_attr, num_color & GUI_COLOR_EXTENDED_MASK); } } else { snprintf (color[index_color], sizeof (color[index_color]), "%s%s", str_attr, gui_weechat_colors[num_color & GUI_COLOR_EXTENDED_MASK].string); } return color[index_color]; } /* * gui_color_build: build a WeeChat color with foreground and background * Foreground and background must be >= 0 and can be a * WeeChat or extended color, with optional attributes for * foreground. */ void gui_color_build (int number, int foreground, int background) { if (foreground < 0) foreground = 0; if (background < 0) background = 0; /* allocate color */ if (!gui_color[number]) { gui_color[number] = malloc (sizeof (*gui_color[number])); if (!gui_color[number]) return; gui_color[number]->string = malloc (4); } /* set foreground and attributes */ if (foreground & GUI_COLOR_EXTENDED_FLAG) { gui_color[number]->foreground = foreground & GUI_COLOR_EXTENDED_MASK; gui_color[number]->attributes = 0; } else { gui_color[number]->foreground = gui_weechat_colors[foreground & GUI_COLOR_EXTENDED_MASK].foreground; gui_color[number]->attributes = gui_weechat_colors[foreground & GUI_COLOR_EXTENDED_MASK].attributes; } if (foreground & GUI_COLOR_EXTENDED_BOLD_FLAG) gui_color[number]->attributes |= A_BOLD; if (foreground & GUI_COLOR_EXTENDED_REVERSE_FLAG) gui_color[number]->attributes |= A_REVERSE; if (foreground & GUI_COLOR_EXTENDED_UNDERLINE_FLAG) gui_color[number]->attributes |= A_UNDERLINE; /* set background */ if (background & GUI_COLOR_EXTENDED_FLAG) gui_color[number]->background = background & GUI_COLOR_EXTENDED_MASK; else gui_color[number]->background = gui_weechat_colors[background & GUI_COLOR_EXTENDED_MASK].background; /* set string */ if (gui_color[number]->string) { snprintf (gui_color[number]->string, 4, "%c%02d", GUI_COLOR_COLOR_CHAR, number); } } /* * gui_color_init_vars: init color variables using terminal infos */ void gui_color_init_vars () { int size; gui_color_term_has_colors = (has_colors ()) ? 1 : 0; gui_color_term_colors = 0; gui_color_term_color_pairs = 0; gui_color_term_can_change_color = 0; gui_color_num_pairs = 63; if (gui_color_pairs) { free (gui_color_pairs); gui_color_pairs = NULL; } gui_color_pairs_used = 0; if (gui_color_term_has_colors) { gui_color_term_colors = COLORS; gui_color_term_color_pairs = COLOR_PAIRS; gui_color_term_can_change_color = (can_change_color ()) ? 1 : 0; gui_color_num_pairs = (gui_color_term_color_pairs >= 256) ? 255 : gui_color_term_color_pairs - 1; if (gui_color_term_colors > 0) { size = (gui_color_term_colors + 2) * (gui_color_term_colors + 2) * sizeof (gui_color_pairs[0]); gui_color_pairs = malloc (size); if (gui_color_pairs) memset (gui_color_pairs, 0, size); gui_color_pairs_used = 0; } /* reserved for future usage */ /* gui_color_term_color_content = malloc (sizeof (gui_color_term_color_content[0]) * (gui_color_term_colors + 1) * 3); if (gui_color_term_color_content) { for (i = 0; i <= gui_color_term_colors; i++) { color_content ((short) i, &gui_color_term_color_content[i * 3], &gui_color_term_color_content[(i * 3) + 1], &gui_color_term_color_content[(i * 3) + 2]); } } */ } } /* * gui_color_free_vars: free color variables */ void gui_color_free_vars () { if (gui_color_pairs) { free (gui_color_pairs); gui_color_pairs = NULL; } if (gui_color_term_color_content) { free (gui_color_term_color_content); gui_color_term_color_content = NULL; } } /* * gui_color_init_pairs_terminal: init color pairs with terminal colors */ void gui_color_init_pairs_terminal () { int i; if (gui_color_term_has_colors) { for (i = 1; i <= gui_color_num_pairs; i++) { init_pair (i, i, -1); } } } /* * gui_color_init_pairs_weechat: init color pairs with WeeChat colors * Pairs defined by WeeChat are set with their * values (from pair 1 to pair N), and other * pairs are set with terminal color and default * background (-1). */ void gui_color_init_pairs_weechat () { int i; short *foregrounds, *backgrounds; if (gui_color_term_has_colors) { gui_color_get_pairs_arrays (&foregrounds, &backgrounds); if (foregrounds && backgrounds) { for (i = 1; i <= gui_color_num_pairs; i++) { if ((foregrounds[i] >= -1) && (backgrounds[i] >= -1)) init_pair (i, foregrounds[i], backgrounds[i]); else init_pair (i, i, -1); } } if (foregrounds) free (foregrounds); if (backgrounds) free (backgrounds); } } /* * gui_color_display_terminal_colors: display terminal colors * This is called by command line option * "-c" / "--colors" */ void gui_color_display_terminal_colors () { int lines, line, col, color; char str_line[1024], str_color[64]; initscr (); if (has_colors ()) { start_color (); use_default_colors (); gui_color_init_vars (); refresh (); endwin (); } printf ("\n"); printf ("%s $TERM=%s COLORS: %d, COLOR_PAIRS: %d, " "can_change_color: %s\n", _("Terminal infos:"), getenv ("TERM"), gui_color_term_colors, gui_color_term_color_pairs, (gui_color_term_can_change_color) ? "yes" : "no"); if (gui_color_term_colors == 0) { printf ("%s\n", _("No color support in terminal.")); } else { printf ("\n"); printf ("%s\n", _("Default colors:")); printf ("------------------------------------------------------------" "--------------------\n"); lines = (gui_color_term_colors < 16) ? gui_color_term_colors : 16; for (line = 0; line < lines; line++) { str_line[0] = '\0'; for (col = 0; col < 16; col++) { color = (col * 16) + line; if (color < gui_color_term_colors) { snprintf (str_color, sizeof (str_color), "\33[0;38;5;%dm %03d ", color, color); strcat (str_line, str_color); } } printf ("%s\n", str_line); } printf ("\33[0m"); printf ("------------------------------------------------------------" "--------------------\n"); } printf ("\n"); gui_color_free_vars (); } /* * gui_color_buffer_display_timer: display line with terminal colors and timer * (remaining time for display of terminal * colors) */ void gui_color_buffer_display_timer () { if (gui_color_buffer && gui_color_use_term_colors) { gui_chat_printf_y (gui_color_buffer, 2, "%s (%d)", _("Terminal colors:"), gui_color_timer); } } /* * gui_color_buffer_display: display content of color buffer */ void gui_color_buffer_display () { int y, i, lines, line, col, color, max_color, num_items; char str_line[1024], str_color[64], str_rgb[64], **items; struct t_gui_color_palette *color_palette; if (!gui_color_buffer) return; gui_buffer_clear (gui_color_buffer); /* set title buffer */ gui_buffer_set_title (gui_color_buffer, _("WeeChat colors | Actions: " "[e] Display extra infos [r] Refresh " "[z] Reset colors [q] Close buffer | " "Keys: [alt-c] Temporarily switch to terminal " "colors")); /* display terminal/colors infos */ y = 0; gui_chat_printf_y (gui_color_buffer, y++, "$TERM=%s COLORS: %d, COLOR_PAIRS: %d, " "can_change_color: %s", getenv ("TERM"), gui_color_term_colors, gui_color_term_color_pairs, (gui_color_term_can_change_color) ? "yes" : "no"); /* display palette of colors */ y++; if (gui_color_use_term_colors) { gui_color_buffer_display_timer (); y++; } else { gui_chat_printf_y (gui_color_buffer, y++, _("WeeChat color pairs (in use: %d, left: %d):"), gui_color_pairs_used, gui_color_num_pairs - gui_color_pairs_used); } max_color = (gui_color_use_term_colors) ? gui_color_term_colors - 1 : gui_color_num_pairs; if (max_color > 255) max_color = 255; lines = (max_color <= 64) ? 8 : 16; for (line = 0; line < lines; line++) { str_line[0] = '\0'; for (col = 0; col < 16; col++) { color = (col * lines) + line; if (color <= max_color) { if (color == 0) { snprintf (str_color, sizeof (str_color), " "); } else if (gui_color_use_term_colors || (color <= gui_color_pairs_used)) { snprintf (str_color, sizeof (str_color), "%c%c%05d%c%03d%c", GUI_COLOR_COLOR_CHAR, GUI_COLOR_EXTENDED_CHAR, color, (color == 0) ? '<' : ' ', color, (color == 0) ? '>' : ' '); } else { snprintf (str_color, sizeof (str_color), "%s - ", GUI_NO_COLOR); } strcat (str_line, str_color); } else { snprintf (str_color, sizeof (str_color), "%s ", GUI_COLOR(GUI_COLOR_CHAT)); strcat (str_line, str_color); } } gui_chat_printf_y (gui_color_buffer, y++, " %s", str_line); } if (gui_color_buffer_extra_info) { /* display WeeChat basic colors */ y++; gui_chat_printf_y (gui_color_buffer, y++, _("WeeChat basic colors:")); str_line[0] = '\0'; for (i = 0; i < GUI_CURSES_NUM_WEECHAT_COLORS; i++) { if (gui_color_use_term_colors) { snprintf (str_color, sizeof (str_color), " %s", gui_weechat_colors[i].string); } else { snprintf (str_color, sizeof (str_color), "%c%c%02d %s", GUI_COLOR_COLOR_CHAR, GUI_COLOR_FG_CHAR, i, gui_weechat_colors[i].string); } if (gui_chat_strlen_screen (str_line) + gui_chat_strlen_screen (str_color) > 80) { gui_chat_printf_y (gui_color_buffer, y++, " %s", str_line); str_line[0] = '\0'; } strcat (str_line, str_color); } if (str_line[0]) { gui_chat_printf_y (gui_color_buffer, y++, " %s", str_line); } /* display nick colors */ y++; gui_chat_printf_y (gui_color_buffer, y++, _("Nick colors:")); items = string_split (CONFIG_STRING(config_color_chat_nick_colors), ",", 0, 0, &num_items); if (items) { str_line[0] = '\0'; for (i = 0; i < num_items; i++) { if (gui_color_use_term_colors) { snprintf (str_color, sizeof (str_color), " %s", items[i]); } else { snprintf (str_color, sizeof (str_color), "%s %s", gui_color_get_custom (items[i]), items[i]); } if (gui_chat_strlen_screen (str_line) + gui_chat_strlen_screen (str_color) > 80) { gui_chat_printf_y (gui_color_buffer, y++, " %s", str_line); str_line[0] = '\0'; } strcat (str_line, str_color); } if (str_line[0]) { gui_chat_printf_y (gui_color_buffer, y++, " %s", str_line); } string_free_split (items); } /* display palette colors */ if (hashtable_get_integer (gui_color_hash_palette_color, "items_count") > 0) { y++; gui_chat_printf_y (gui_color_buffer, y++, _("Color aliases:")); for (i = 1; i <= gui_color_num_pairs; i++) { color_palette = gui_color_palette_get (i); if (color_palette) { str_color[0] = '\0'; if (!gui_color_use_term_colors) { snprintf (str_color, sizeof (str_color), "%c%c%c%05d", GUI_COLOR_COLOR_CHAR, GUI_COLOR_FG_CHAR, GUI_COLOR_EXTENDED_CHAR, i); } str_rgb[0] = '\0'; if ((color_palette->r >= 0) && (color_palette->g >= 0) && (color_palette->b >= 0)) { snprintf (str_rgb, sizeof (str_rgb), " (%d/%d/%d)", color_palette->r, color_palette->g, color_palette->b); } gui_chat_printf_y (gui_color_buffer, y++, " %5d: %s%s%s", i, str_color, (color_palette->alias) ? color_palette->alias : "", str_rgb); } } } /* display content of colors */ if (gui_color_term_color_content) { y++; gui_chat_printf_y (gui_color_buffer, y++, _("Content of colors (r/g/b):")); for (i = 0; i < gui_color_term_colors; i++) { gui_chat_printf_y (gui_color_buffer, y++, " %3d: %4hd / %4hd / %4hd", i, gui_color_term_color_content[i * 3], gui_color_term_color_content[(i* 3) + 1], gui_color_term_color_content[(i* 3) + 2]); } } } } /* * gui_color_timer_cb: callback for timer */ int gui_color_timer_cb (void *data, int remaining_calls) { /* make C compiler happy */ (void) data; (void) remaining_calls; gui_color_timer--; if (gui_color_timer <= 0) { if (gui_color_use_term_colors) gui_color_switch_colors (); } else { if (gui_color_buffer && gui_color_use_term_colors) { gui_color_buffer_display_timer (); } } return WEECHAT_RC_OK; } /* * gui_color_switch_colrs: switch between WeeChat and terminal colors */ void gui_color_switch_colors () { if (gui_color_hook_timer) { unhook (gui_color_hook_timer); gui_color_hook_timer = NULL; } /* * when we press alt-c many times quickly, this just adds some time for * display of terminal colors */ if (gui_color_use_term_colors && (gui_color_timer > 0) && (gui_color_timer % 10 == 0)) { if (gui_color_timer < 120) gui_color_timer += 10; gui_color_buffer_display_timer (); } else { gui_color_use_term_colors ^= 1; if (gui_color_use_term_colors) gui_color_init_pairs_terminal (); else gui_color_init_pairs_weechat (); gui_color_buffer_refresh_needed = 1; gui_window_ask_refresh (1); if (gui_color_use_term_colors) gui_color_timer = GUI_COLOR_TIMER_TERM_COLORS; } if (gui_color_use_term_colors) { gui_color_hook_timer = hook_timer (NULL, 1000, 0, 0, &gui_color_timer_cb, NULL); } } /* * gui_color_reset_pairs: reset all color pairs * (the next refresh will auto reallocate needed pairs) * It is useful when color pairs table is full, to * remove non used pairs. */ void gui_color_reset_pairs () { if (gui_color_pairs) { memset (gui_color_pairs, 0, (gui_color_term_colors + 2) * (gui_color_term_colors + 2) * sizeof (gui_color_pairs[0])); gui_color_pairs_used = 0; gui_color_warning_pairs_full = 0; gui_color_buffer_refresh_needed = 1; gui_window_ask_refresh (1); } } /* * gui_color_buffer_input_cb: input callback for color buffer */ int gui_color_buffer_input_cb (void *data, struct t_gui_buffer *buffer, const char *input_data) { /* make C compiler happy */ (void) data; if (string_strcasecmp (input_data, "e") == 0) { gui_color_buffer_extra_info ^= 1; gui_color_buffer_display (); } else if (string_strcasecmp (input_data, "r") == 0) { gui_color_buffer_display (); } else if (string_strcasecmp (input_data, "q") == 0) { gui_buffer_close (buffer); } else if (string_strcasecmp (input_data, "z") == 0) { gui_color_reset_pairs (buffer); } return WEECHAT_RC_OK; } /* * gui_color_buffer_close_cb: close callback for color buffer */ int gui_color_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { /* make C compiler happy */ (void) data; (void) buffer; gui_color_buffer = NULL; return WEECHAT_RC_OK; } /* * gui_color_buffer_assign: assign color buffer to pointer if it is not yet set */ void gui_color_buffer_assign () { if (!gui_color_buffer) { gui_color_buffer = gui_buffer_search_by_name (NULL, "color"); if (gui_color_buffer) { gui_color_buffer->input_callback = &gui_color_buffer_input_cb; gui_color_buffer->close_callback = &gui_color_buffer_close_cb; } } } /* * gui_color_buffer_open: open a buffer to display colors */ void gui_color_buffer_open () { if (!gui_color_buffer) { gui_color_buffer = gui_buffer_new (NULL, "color", &gui_color_buffer_input_cb, NULL, &gui_color_buffer_close_cb, NULL); if (gui_color_buffer) { gui_buffer_set (gui_color_buffer, "type", "free"); gui_buffer_set (gui_color_buffer, "localvar_set_no_log", "1"); gui_buffer_set (gui_color_buffer, "key_bind_meta-c", "/color switch"); } } if (!gui_color_buffer) return; gui_window_switch_to_buffer (gui_current_window, gui_color_buffer, 1); gui_color_buffer_display (); } /* * gui_color_palette_add_alias_cb: add an alias in hashtable with aliases */ void gui_color_palette_add_alias_cb (void *data, struct t_hashtable *hashtable, const void *key, const void *value) { struct t_gui_color_palette *color_palette; char *error; int number; /* make C compiler happy */ (void) data; (void) hashtable; color_palette = (struct t_gui_color_palette *)value; if (color_palette && color_palette->alias) { error = NULL; number = (int)strtol ((char *)key, &error, 10); if (error && !error[0]) { hashtable_set (gui_color_hash_palette_alias, color_palette->alias, &number); } } } /* * gui_color_palette_build_aliases: build aliases for palette */ void gui_color_palette_build_aliases () { int i; struct t_gui_color_palette *color_palette; char str_number[64]; if (!gui_color_hash_palette_alias || !gui_color_list_with_alias || !gui_color_hash_palette_color) { gui_color_palette_alloc_structs (); } hashtable_remove_all (gui_color_hash_palette_alias); weelist_remove_all (gui_color_list_with_alias); for (i = 0; i < GUI_CURSES_NUM_WEECHAT_COLORS; i++) { weelist_add (gui_color_list_with_alias, gui_weechat_colors[i].string, WEECHAT_LIST_POS_END, NULL); } for (i = 0; i <= gui_color_term_colors; i++) { color_palette = gui_color_palette_get (i); if (color_palette) { weelist_add (gui_color_list_with_alias, color_palette->alias, WEECHAT_LIST_POS_END, NULL); } else { snprintf (str_number, sizeof (str_number), "%d", i); weelist_add (gui_color_list_with_alias, str_number, WEECHAT_LIST_POS_END, NULL); } } hashtable_map (gui_color_hash_palette_color, &gui_color_palette_add_alias_cb, NULL); } /* * gui_color_palette_new: create a new color in palette */ struct t_gui_color_palette * gui_color_palette_new (int number, const char *value) { struct t_gui_color_palette *new_color_palette; char **items, *pos, *pos2, *error1, *error2, *error3; char *str_alias, *str_rgb, str_number[64]; int num_items, i, r, g, b; if (!value) return NULL; new_color_palette = malloc (sizeof (*new_color_palette)); if (new_color_palette) { new_color_palette->alias = NULL; new_color_palette->r = -1; new_color_palette->g = -1; new_color_palette->b = -1; str_alias = NULL; str_rgb = NULL; items = string_split (value, ";", 0, 0, &num_items); if (items) { for (i = 0; i < num_items; i++) { pos = strchr (items[i], '/'); if (pos) str_rgb = items[i]; else { pos = strchr (items[i], ','); if (!pos) str_alias = items[i]; } } if (str_alias) { new_color_palette->alias = strdup (str_alias); } if (str_rgb) { pos = strchr (str_rgb, '/'); if (pos) { pos[0] = '\0'; pos2 = strchr (pos + 1, '/'); if (pos2) { pos2[0] = '\0'; error1 = NULL; r = (int)strtol (str_rgb, &error1, 10); error2 = NULL; g = (int)strtol (pos + 1, &error2, 10); error3 = NULL; b = (int)strtol (pos2 + 1, &error3, 10); if (error1 && !error1[0] && error2 && !error2[0] && error3 && !error3[0] && (r >= 0) && (r <= 1000) && (g >= 0) && (g <= 1000) && (b >= 0) && (b <= 1000)) { new_color_palette->r = r; new_color_palette->g = g; new_color_palette->b = b; } } } } string_free_split (items); } if (!new_color_palette->alias) { snprintf (str_number, sizeof (str_number), "%d", number); new_color_palette->alias = strdup (str_number); } } return new_color_palette; } /* * gui_color_palette_free: free a color in palette */ void gui_color_palette_free (struct t_gui_color_palette *color_palette) { if (!color_palette) return; if (color_palette->alias) free (color_palette->alias); free (color_palette); } /* * gui_color_init_weechat: init WeeChat colors */ void gui_color_init_weechat () { gui_color_build (GUI_COLOR_SEPARATOR, CONFIG_COLOR(config_color_separator), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT, CONFIG_COLOR(config_color_chat), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_TIME, CONFIG_COLOR(config_color_chat_time), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_TIME_DELIMITERS, CONFIG_COLOR(config_color_chat_time_delimiters), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_ERROR, CONFIG_COLOR(config_color_chat_prefix[GUI_CHAT_PREFIX_ERROR]), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_NETWORK, CONFIG_COLOR(config_color_chat_prefix[GUI_CHAT_PREFIX_NETWORK]), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_ACTION, CONFIG_COLOR(config_color_chat_prefix[GUI_CHAT_PREFIX_ACTION]), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_JOIN, CONFIG_COLOR(config_color_chat_prefix[GUI_CHAT_PREFIX_JOIN]), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_QUIT, CONFIG_COLOR(config_color_chat_prefix[GUI_CHAT_PREFIX_QUIT]), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_MORE, CONFIG_COLOR(config_color_chat_prefix_more), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_PREFIX_SUFFIX, CONFIG_COLOR(config_color_chat_prefix_suffix), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_BUFFER, CONFIG_COLOR(config_color_chat_buffer), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_SERVER, CONFIG_COLOR(config_color_chat_server), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_CHANNEL, CONFIG_COLOR(config_color_chat_channel), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK, CONFIG_COLOR(config_color_chat_nick), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK_SELF, CONFIG_COLOR(config_color_chat_nick_self), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK_OTHER, CONFIG_COLOR(config_color_chat_nick_other), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_HOST, CONFIG_COLOR(config_color_chat_host), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_DELIMITERS, CONFIG_COLOR(config_color_chat_delimiters), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_HIGHLIGHT, CONFIG_COLOR(config_color_chat_highlight), CONFIG_COLOR(config_color_chat_highlight_bg)); 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)); /* * define old nick colors for compatibility on /upgrade with previous * versions: these colors have been removed in version 0.3.4 and replaced * by new option "weechat.color.chat_nick_colors", which is a list of * colors (without limit on number of colors) */ gui_color_build (GUI_COLOR_CHAT_NICK1_OBSOLETE, gui_color_search ("cyan"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK2_OBSOLETE, gui_color_search ("magenta"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK3_OBSOLETE, gui_color_search ("green"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK4_OBSOLETE, gui_color_search ("brown"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK5_OBSOLETE, gui_color_search ("lightblue"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK6_OBSOLETE, gui_color_search ("default"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK7_OBSOLETE, gui_color_search ("lightcyan"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK8_OBSOLETE, gui_color_search ("lightmagenta"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK9_OBSOLETE, gui_color_search ("lightgreen"), CONFIG_COLOR(config_color_chat_bg)); gui_color_build (GUI_COLOR_CHAT_NICK10_OBSOLETE, gui_color_search ("blue"), CONFIG_COLOR(config_color_chat_bg)); } /* * gui_color_pre_init: pre-init colors */ void gui_color_pre_init () { int i; for (i = 0; i < GUI_COLOR_NUM_COLORS; i++) { gui_color[i] = NULL; } } /* * gui_color_init: init GUI colors */ void gui_color_init () { if (has_colors()) { start_color (); use_default_colors (); } gui_color_init_vars (); gui_color_init_pairs_terminal (); gui_color_init_weechat (); gui_color_palette_build_aliases (); } /* * gui_color_dump: dump colors */ void gui_color_dump () { int fg, bg, index, used; gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("WeeChat colors (in use: %d, left: %d):"), gui_color_pairs_used, gui_color_num_pairs - gui_color_pairs_used); if (gui_color_pairs) { used = 0; for (bg = -1; bg <= gui_color_term_colors; bg++) { for (fg = -1; fg <= gui_color_term_colors; fg++) { index = ((bg + 1) * (gui_color_term_colors + 2)) + (fg + 1); if (gui_color_pairs[index] >= 1) { gui_chat_printf (NULL, " fg:%3d, bg:%3d, pairs[%05d] = %hd", fg, bg, index, gui_color_pairs[index]); used++; } } } } } /* * gui_color_end: end GUI colors */ void gui_color_end () { int i; for (i = 0; i < GUI_COLOR_NUM_COLORS; i++) { gui_color_free (gui_color[i]); } gui_color_palette_free_structs (); gui_color_free_vars (); }