weechat/src/gui/gui-bar.c

2431 lines
77 KiB
C

/*
* gui-bar.c - bar functions (used by all GUI)
*
* Copyright (C) 2003-2020 Sébastien Helleu <flashcode@flashtux.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
#include "../core/weechat.h"
#include "../core/wee-config.h"
#include "../core/wee-eval.h"
#include "../core/wee-hashtable.h"
#include "../core/wee-hdata.h"
#include "../core/wee-hook.h"
#include "../core/wee-infolist.h"
#include "../core/wee-log.h"
#include "../core/wee-string.h"
#include "../plugins/plugin.h"
#include "gui-bar.h"
#include "gui-bar-item.h"
#include "gui-bar-window.h"
#include "gui-buffer.h"
#include "gui-chat.h"
#include "gui-color.h"
#include "gui-window.h"
char *gui_bar_option_string[GUI_BAR_NUM_OPTIONS] =
{ "hidden", "priority", "type", "conditions", "position", "filling_top_bottom",
"filling_left_right", "size", "size_max", "color_fg", "color_delim",
"color_bg", "separator", "items" };
char *gui_bar_option_default[GUI_BAR_NUM_OPTIONS] =
{ "0", "0", "0", "", "top", "horizontal",
"vertical", "0", "0", "default", "default",
"default", "off", "" };
char *gui_bar_type_string[GUI_BAR_NUM_TYPES] =
{ "root", "window" };
char *gui_bar_position_string[GUI_BAR_NUM_POSITIONS] =
{ "bottom", "top", "left", "right" };
char *gui_bar_filling_string[GUI_BAR_NUM_FILLING] =
{ "horizontal", "vertical", "columns_horizontal", "columns_vertical" };
struct t_gui_bar *gui_bars = NULL; /* first bar */
struct t_gui_bar *last_gui_bar = NULL; /* last bar */
struct t_gui_bar *gui_temp_bars = NULL; /* bars used when reading config */
struct t_gui_bar *last_gui_temp_bar = NULL;
void gui_bar_free_bar_windows (struct t_gui_bar *bar);
/*
* Checks if a bar pointer is valid.
*
* Returns:
* 1: bar exists
* 0: bar does not exist
*/
int
gui_bar_valid (struct t_gui_bar *bar)
{
struct t_gui_bar *ptr_bar;
if (!bar)
return 0;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (ptr_bar == bar)
return 1;
}
/* bar not found */
return 0;
}
/*
* Searches for a bar option name.
*
* Returns index of option in enum t_gui_bar_option, -1 if not found.
*/
int
gui_bar_search_option (const char *option_name)
{
int i;
if (!option_name)
return -1;
for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++)
{
if (string_strcasecmp (gui_bar_option_string[i], option_name) == 0)
return i;
}
/* bar option not found */
return -1;
}
/*
* Searches for a bar type.
*
* Returns index of type in enum t_gui_bar_type, -1 if not found.
*/
int
gui_bar_search_type (const char *type)
{
int i;
if (!type)
return -1;
for (i = 0; i < GUI_BAR_NUM_TYPES; i++)
{
if (string_strcasecmp (gui_bar_type_string[i], type) == 0)
return i;
}
/* type not found */
return -1;
}
/*
* Searches for a bar position.
*
* Returns index of position in enum t_gui_bar_position, -1 if not found.
*/
int
gui_bar_search_position (const char *position)
{
int i;
if (!position)
return -1;
for (i = 0; i < GUI_BAR_NUM_POSITIONS; i++)
{
if (string_strcasecmp (gui_bar_position_string[i], position) == 0)
return i;
}
/* position not found */
return -1;
}
/*
* Checks if "add_size" is OK for bar.
*
* Returns:
* 1: new size is OK
* 0: new size is too big
*/
int
gui_bar_check_size_add (struct t_gui_bar *bar, int add_size)
{
struct t_gui_window *ptr_window;
int sub_width, sub_height;
sub_width = 0;
sub_height = 0;
switch (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_POSITION]))
{
case GUI_BAR_POSITION_BOTTOM:
case GUI_BAR_POSITION_TOP:
sub_height = add_size;
break;
case GUI_BAR_POSITION_LEFT:
case GUI_BAR_POSITION_RIGHT:
sub_width = add_size;
break;
case GUI_BAR_NUM_POSITIONS:
break;
}
for (ptr_window = gui_windows; ptr_window;
ptr_window = ptr_window->next_window)
{
if ((CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
|| (gui_bar_window_search_bar (ptr_window, bar)))
{
if ((ptr_window->win_chat_width - sub_width < 1)
|| (ptr_window->win_chat_height - sub_height < 1))
return 0;
}
}
/* new size OK */
return 1;
}
/*
* Returns filling option for bar, according to filling for current bar
* position.
*/
enum t_gui_bar_filling
gui_bar_get_filling (struct t_gui_bar *bar)
{
if ((CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_POSITION]) == GUI_BAR_POSITION_BOTTOM)
|| (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_POSITION]) == GUI_BAR_POSITION_TOP))
return CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM]);
return CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT]);
}
/*
* Searches for position of a bar in list (to keep list sorted by priority).
*/
struct t_gui_bar *
gui_bar_find_pos (struct t_gui_bar *bar)
{
struct t_gui_bar *ptr_bar;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_PRIORITY]) >= CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_PRIORITY]))
return ptr_bar;
}
/* bar not found, add to end of list */
return NULL;
}
/*
* Inserts a bar to the list (at good position, according to priority).
*/
void
gui_bar_insert (struct t_gui_bar *bar)
{
struct t_gui_bar *pos_bar;
if (gui_bars)
{
pos_bar = gui_bar_find_pos (bar);
if (pos_bar)
{
/* insert bar into the list (before position found) */
bar->prev_bar = pos_bar->prev_bar;
bar->next_bar = pos_bar;
if (pos_bar->prev_bar)
(pos_bar->prev_bar)->next_bar = bar;
else
gui_bars = bar;
pos_bar->prev_bar = bar;
}
else
{
/* add bar to the end */
bar->prev_bar = last_gui_bar;
bar->next_bar = NULL;
last_gui_bar->next_bar = bar;
last_gui_bar = bar;
}
}
else
{
bar->prev_bar = NULL;
bar->next_bar = NULL;
gui_bars = bar;
last_gui_bar = bar;
}
}
/*
* Checks if bar must be displayed in window according to conditions.
*
* If window is NULL (case of root bars), the current window is used.
*
* Returns:
* 1: bar must be displayed
* 0: bar must not be displayed
*/
int
gui_bar_check_conditions (struct t_gui_bar *bar,
struct t_gui_window *window)
{
int rc;
char str_modifier[256], str_window[128], *str_displayed, *result;
const char *conditions;
struct t_hashtable *pointers, *extra_vars, *options;
if (!window)
window = gui_current_window;
/* check bar condition(s) */
conditions = CONFIG_STRING(bar->options[GUI_BAR_OPTION_CONDITIONS]);
if (string_strcasecmp (conditions, "active") == 0)
{
if (gui_current_window && (gui_current_window != window))
return 0;
}
else if (string_strcasecmp (conditions, "inactive") == 0)
{
if (!gui_current_window || (gui_current_window == window))
return 0;
}
else if (string_strcasecmp (conditions, "nicklist") == 0)
{
if (window && window->buffer && !window->buffer->nicklist)
return 0;
}
else if (conditions[0])
{
pointers = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_POINTER,
NULL, NULL);
if (pointers)
{
hashtable_set (pointers, "window", window);
if (window)
hashtable_set (pointers, "buffer", window->buffer);
}
extra_vars = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
if (extra_vars)
{
hashtable_set (extra_vars, "active",
(gui_current_window && (gui_current_window == window)) ? "1" : "0");
hashtable_set (extra_vars, "inactive",
(gui_current_window && (gui_current_window != window)) ? "1" : "0");
hashtable_set (extra_vars, "nicklist",
(window && window->buffer && window->buffer->nicklist) ? "1" : "0");
}
options = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
if (options)
hashtable_set (options, "type", "condition");
result = eval_expression (conditions, pointers, extra_vars, options);
rc = eval_is_true (result);
if (result)
free (result);
if (pointers)
hashtable_free (pointers);
if (extra_vars)
hashtable_free (extra_vars);
if (options)
hashtable_free (options);
if (!rc)
return 0;
}
/*
* call a modifier that will tell us if bar is displayed or not,
* for example it can be used to display nicklist on some buffers
* only, using a script that implements this modifier and return "1"
* to display bar, "0" to hide it
*/
snprintf (str_modifier, sizeof (str_modifier),
"bar_condition_%s", bar->name);
snprintf (str_window, sizeof (str_window),
"0x%lx", (unsigned long)(window));
str_displayed = hook_modifier_exec (NULL,
str_modifier,
str_window,
"");
if (str_displayed && strcmp (str_displayed, "0") == 0)
rc = 0;
else
rc = 1;
if (str_displayed)
free (str_displayed);
return rc;
}
/*
* Gets total bar size ("root" type) for a position.
*/
int
gui_bar_root_get_size (struct t_gui_bar *bar, enum t_gui_bar_position position)
{
struct t_gui_bar *ptr_bar;
int total_size;
total_size = 0;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (bar && (ptr_bar == bar))
return total_size;
if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN])
&& ptr_bar->bar_window)
{
if ((CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
&& (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_POSITION]) == (int)position))
{
total_size += gui_bar_window_get_current_size (ptr_bar->bar_window);
if (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SEPARATOR]))
total_size++;
}
}
}
return total_size;
}
/*
* Searches for a bar by name.
*
* Returns pointer to bar found, NULL if not found.
*/
struct t_gui_bar *
gui_bar_search (const char *name)
{
struct t_gui_bar *ptr_bar;
if (!name || !name[0])
return NULL;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (string_strcasecmp (ptr_bar->name, name) == 0)
return ptr_bar;
}
/* bar not found */
return NULL;
}
/*
* Searches for a bar with name of option (like "status.type").
*
* Returns pointer to bar found, NULL if not found.
*/
struct t_gui_bar *
gui_bar_search_with_option_name (const char *option_name)
{
char *bar_name, *pos_option;
struct t_gui_bar *ptr_bar;
ptr_bar = NULL;
pos_option = strchr (option_name, '.');
if (pos_option)
{
bar_name = string_strndup (option_name, pos_option - option_name);
if (bar_name)
{
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (string_strcasecmp (ptr_bar->name, bar_name) == 0)
break;
}
free (bar_name);
}
}
return ptr_bar;
}
/*
* Rebuilds content of bar windows for a bar.
*/
void
gui_bar_content_build_bar_windows (struct t_gui_bar *bar)
{
struct t_gui_window *ptr_window;
struct t_gui_bar_window *ptr_bar_window;
if (!bar)
return;
if (bar->bar_window)
{
gui_bar_window_content_build (bar->bar_window, NULL);
}
else
{
for (ptr_window = gui_windows; ptr_window;
ptr_window = ptr_window->next_window)
{
for (ptr_bar_window = ptr_window->bar_windows; ptr_bar_window;
ptr_bar_window = ptr_bar_window->next_bar_window)
{
if (ptr_bar_window->bar == bar)
gui_bar_window_content_build (ptr_bar_window, ptr_window);
}
}
}
}
/*
* Asks refresh for bar.
*/
void
gui_bar_ask_refresh (struct t_gui_bar *bar)
{
bar->bar_refresh_needed = 1;
}
/*
* Asks for bar refresh on screen (for all windows where bar is).
*/
void
gui_bar_refresh (struct t_gui_bar *bar)
{
struct t_gui_window *ptr_win;
if (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
gui_window_ask_refresh (1);
else
{
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
if (gui_bar_window_search_bar (ptr_win, bar))
ptr_win->refresh_needed = 1;
}
}
}
/*
* Draws a bar.
*/
void
gui_bar_draw (struct t_gui_bar *bar)
{
struct t_gui_window *ptr_win;
struct t_gui_bar_window *ptr_bar_win;
if (!CONFIG_BOOLEAN(bar->options[GUI_BAR_OPTION_HIDDEN]))
{
if (bar->bar_window)
{
/* root bar */
gui_bar_window_draw (bar->bar_window, NULL);
}
else
{
/* bar on each window */
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
for (ptr_bar_win = ptr_win->bar_windows; ptr_bar_win;
ptr_bar_win = ptr_bar_win->next_bar_window)
{
if (ptr_bar_win->bar == bar)
{
gui_bar_window_draw (ptr_bar_win, ptr_win);
}
}
}
}
}
bar->bar_refresh_needed = 0;
}
/*
* Applies new size for all bar windows of bar.
*/
void
gui_bar_apply_current_size (struct t_gui_bar *bar)
{
struct t_gui_window *ptr_win;
struct t_gui_bar_window *ptr_bar_win;
if (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
{
gui_bar_window_set_current_size (bar->bar_window,
NULL,
CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_SIZE]));
gui_window_ask_refresh (1);
}
else
{
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
for (ptr_bar_win = ptr_win->bar_windows; ptr_bar_win;
ptr_bar_win = ptr_bar_win->next_bar_window)
{
if (ptr_bar_win->bar == bar)
{
gui_bar_window_set_current_size (ptr_bar_win,
ptr_win,
CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_SIZE]));
}
}
}
}
}
/*
* Frees arrays with items for a bar.
*/
void
gui_bar_free_items_arrays (struct t_gui_bar *bar)
{
int i, j;
for (i = 0; i < bar->items_count; i++)
{
if (bar->items_array[i])
string_free_split (bar->items_array[i]);
for (j = 0; j < bar->items_subcount[i]; j++)
{
if (bar->items_buffer[i][j])
free (bar->items_buffer[i][j]);
if (bar->items_prefix[i][j])
free (bar->items_prefix[i][j]);
if (bar->items_name[i][j])
free (bar->items_name[i][j]);
if (bar->items_suffix[i][j])
free (bar->items_suffix[i][j]);
}
if (bar->items_buffer[i])
free (bar->items_buffer[i]);
if (bar->items_prefix[i])
free (bar->items_prefix[i]);
if (bar->items_name[i])
free (bar->items_name[i]);
if (bar->items_suffix[i])
free (bar->items_suffix[i]);
}
if (bar->items_array)
{
free (bar->items_array);
bar->items_array = NULL;
}
if (bar->items_buffer)
{
free (bar->items_buffer);
bar->items_buffer = NULL;
}
if (bar->items_prefix)
{
free (bar->items_prefix);
bar->items_prefix = NULL;
}
if (bar->items_name)
{
free (bar->items_name);
bar->items_name = NULL;
}
if (bar->items_suffix)
{
free (bar->items_suffix);
bar->items_suffix = NULL;
}
if (bar->items_subcount)
{
free (bar->items_subcount);
bar->items_subcount = NULL;
}
bar->items_count = 0;
}
/*
* Builds array with items for a bar.
*/
void
gui_bar_set_items_array (struct t_gui_bar *bar, const char *items)
{
int i, j, count;
char **tmp_array;
gui_bar_free_items_arrays (bar);
if (items && items[0])
{
tmp_array = string_split (items, ",", NULL,
WEECHAT_STRING_SPLIT_STRIP_LEFT
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0, &count);
if (count > 0)
{
bar->items_count = count;
bar->items_subcount = malloc (count * sizeof (*bar->items_subcount));
bar->items_array = malloc (count * sizeof (*bar->items_array));
bar->items_buffer = malloc (count * sizeof (*bar->items_buffer));
bar->items_prefix = malloc (count * sizeof (*bar->items_prefix));
bar->items_name = malloc (count * sizeof (*bar->items_name));
bar->items_suffix = malloc (count * sizeof (*bar->items_suffix));
for (i = 0; i < count; i++)
{
bar->items_array[i] = string_split (
tmp_array[i],
"+",
NULL,
WEECHAT_STRING_SPLIT_STRIP_LEFT
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0,
&(bar->items_subcount[i]));
if (bar->items_subcount[i] > 0)
{
bar->items_buffer[i] = malloc (bar->items_subcount[i] *
sizeof (*(bar->items_buffer[i])));
bar->items_prefix[i] = malloc (bar->items_subcount[i] *
sizeof (*(bar->items_prefix[i])));
bar->items_name[i] = malloc (bar->items_subcount[i] *
sizeof (*(bar->items_name[i])));
bar->items_suffix[i] = malloc (bar->items_subcount[i] *
sizeof (*(bar->items_suffix[i])));
for (j = 0; j < bar->items_subcount[i]; j++)
{
gui_bar_item_get_vars (bar->items_array[i][j],
&bar->items_buffer[i][j],
&bar->items_prefix[i][j],
&bar->items_name[i][j],
&bar->items_suffix[i][j]);
}
}
}
}
string_free_split (tmp_array);
}
}
/*
* Callback for checking bar type before changing it.
*
* Returns always 0 because changing the type of a bar is not allowed.
*/
int
gui_bar_config_check_type (const void *pointer, void *data,
struct t_config_option *option,
const char *value)
{
/* make C compiler happy */
(void) pointer;
(void) data;
(void) option;
(void) value;
gui_chat_printf (NULL,
_("%sUnable to change bar type: you must delete bar "
"and create another to do that"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
return 0;
}
/*
* Callback called when "hidden" flag is changed.
*/
void
gui_bar_config_change_hidden (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
struct t_gui_window *ptr_win;
struct t_gui_bar_window *ptr_bar_win, *next_bar_win;
int bar_window_exists;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar)
{
if (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
{
if (CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
if (ptr_bar->bar_window)
gui_bar_window_free (ptr_bar->bar_window, NULL);
}
else
{
if (!ptr_bar->bar_window)
gui_bar_window_new (ptr_bar, NULL);
}
}
else
{
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
bar_window_exists = 0;
ptr_bar_win = ptr_win->bar_windows;
while (ptr_bar_win)
{
next_bar_win = ptr_bar_win->next_bar_window;
if (ptr_bar_win->bar == ptr_bar)
{
if (CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_window_free (ptr_bar_win, ptr_win);
else
bar_window_exists = 1;
}
ptr_bar_win = next_bar_win;
}
if (!bar_window_exists
&& !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
gui_bar_window_new (ptr_bar, ptr_win);
}
}
}
gui_window_ask_refresh (1);
}
}
/*
* Callback called when "priority" is changed.
*/
void
gui_bar_config_change_priority (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
struct t_gui_window *ptr_win;
struct t_gui_bar_window *bar_windows, *ptr_bar_win, *next_bar_win;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar)
{
/* remove bar from list */
if (ptr_bar == gui_bars)
{
gui_bars = ptr_bar->next_bar;
gui_bars->prev_bar = NULL;
}
if (ptr_bar == last_gui_bar)
{
last_gui_bar = ptr_bar->prev_bar;
last_gui_bar->next_bar = NULL;
}
if (ptr_bar->prev_bar)
(ptr_bar->prev_bar)->next_bar = ptr_bar->next_bar;
if (ptr_bar->next_bar)
(ptr_bar->next_bar)->prev_bar = ptr_bar->prev_bar;
gui_bar_insert (ptr_bar);
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
bar_windows = ptr_win->bar_windows;
ptr_win->bar_windows = NULL;
ptr_win->last_bar_window = NULL;
ptr_bar_win = bar_windows;
while (ptr_bar_win)
{
next_bar_win = ptr_bar_win->next_bar_window;
gui_bar_window_insert (ptr_bar_win, ptr_win);
ptr_bar_win = next_bar_win;
}
}
gui_window_ask_refresh (1);
}
}
/*
* Callback called when "conditions" is changed.
*/
void
gui_bar_config_change_conditions (const void *pointer, void *data,
struct t_config_option *option)
{
/* make C compiler happy */
(void) pointer;
(void) data;
(void) option;
gui_window_ask_refresh (1);
}
/*
* Callback called when "position" is changed.
*/
void
gui_bar_config_change_position (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_refresh (ptr_bar);
gui_window_ask_refresh (1);
}
/*
* Callback called when "filling" is changed.
*/
void
gui_bar_config_change_filling (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_refresh (ptr_bar);
gui_window_ask_refresh (1);
}
/*
* Callback for checking bar size before changing it.
*
* Returns:
* 1: new size is OK
* 0: new size is NOT OK
*/
int
gui_bar_config_check_size (const void *pointer, void *data,
struct t_config_option *option,
const char *value)
{
struct t_gui_bar *ptr_bar;
long number;
char *error;
int new_value, current_size;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar)
{
new_value = -1;
if (strncmp (value, "++", 2) == 0)
{
error = NULL;
number = strtol (value + 2, &error, 10);
if (error && !error[0])
{
new_value = CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE]) + number;
}
}
else if (strncmp (value, "--", 2) == 0)
{
error = NULL;
number = strtol (value + 2, &error, 10);
if (error && !error[0])
{
new_value = CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE]) - number;
}
}
else
{
error = NULL;
number = strtol (value, &error, 10);
if (error && !error[0])
{
new_value = number;
}
}
if (new_value < 0)
return 0;
if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
current_size = CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE]);
if ((current_size == 0) && ptr_bar->bar_window)
current_size = ptr_bar->bar_window->current_size;
if ((new_value > 0) && (new_value > current_size)
&& !gui_bar_check_size_add (ptr_bar, new_value - current_size))
{
return 0;
}
}
return 1;
}
return 0;
}
/*
* Callback called when "size" is changed.
*/
void
gui_bar_config_change_size (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
gui_bar_apply_current_size (ptr_bar);
gui_bar_refresh (ptr_bar);
}
}
/*
* Callback called when "size_max" is changed.
*/
void
gui_bar_config_change_size_max (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
char value[32];
/* make C compiler happy */
(void) pointer;
(void) data;
(void) option;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
if ((CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE_MAX]) > 0)
&& (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE]) >
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE_MAX])))
{
snprintf (value, sizeof (value), "%d",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE_MAX]));
config_file_option_set (ptr_bar->options[GUI_BAR_OPTION_SIZE], value, 1);
}
gui_window_ask_refresh (1);
}
}
/*
* Callback when color (fg or bg) is changed.
*/
void
gui_bar_config_change_color (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_refresh (ptr_bar);
}
/*
* Callback called when "separator" is changed.
*/
void
gui_bar_config_change_separator (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_refresh (ptr_bar);
}
/*
* Callback called when "items" is changed.
*/
void
gui_bar_config_change_items (const void *pointer, void *data,
struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
/* make C compiler happy */
(void) pointer;
(void) data;
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar)
{
gui_bar_set_items_array (ptr_bar, CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS]));
gui_bar_content_build_bar_windows (ptr_bar);
if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
gui_bar_ask_refresh (ptr_bar);
}
}
/*
* Sets name for a bar.
*/
void
gui_bar_set_name (struct t_gui_bar *bar, const char *name)
{
int length;
char *option_name;
if (!name || !name[0])
return;
length = strlen (name) + 64;
option_name = malloc (length);
if (option_name)
{
snprintf (option_name, length, "%s.hidden", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_HIDDEN], option_name);
snprintf (option_name, length, "%s.priority", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_PRIORITY], option_name);
snprintf (option_name, length, "%s.type", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_TYPE], option_name);
snprintf (option_name, length, "%s.conditions", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_CONDITIONS], option_name);
snprintf (option_name, length, "%s.position", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_POSITION], option_name);
snprintf (option_name, length, "%s.filling_top_bottom", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM], option_name);
snprintf (option_name, length, "%s.filling_left_right", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT], option_name);
snprintf (option_name, length, "%s.size", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_SIZE], option_name);
snprintf (option_name, length, "%s.size_max", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_SIZE_MAX], option_name);
snprintf (option_name, length, "%s.color_fg", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_COLOR_FG], option_name);
snprintf (option_name, length, "%s.color_delim", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_COLOR_DELIM], option_name);
snprintf (option_name, length, "%s.color_bg", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_COLOR_BG], option_name);
snprintf (option_name, length, "%s.separator", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_SEPARATOR], option_name);
snprintf (option_name, length, "%s.items", name);
config_file_option_rename (bar->options[GUI_BAR_OPTION_ITEMS], option_name);
if (bar->name)
free (bar->name);
bar->name = strdup (name);
free (option_name);
}
}
/*
* Sets a property for a bar.
*
* Returns:
* 1: OK
* 0: error
*/
int
gui_bar_set (struct t_gui_bar *bar, const char *property, const char *value)
{
if (!bar || !property || !value)
return 0;
if (string_strcasecmp (property, "name") == 0)
{
gui_bar_set_name (bar, value);
return 1;
}
else if (string_strcasecmp (property, "hidden") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_HIDDEN], value, 1);
return 1;
}
else if (string_strcasecmp (property, "priority") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_PRIORITY], value, 1);
return 1;
}
else if (string_strcasecmp (property, "conditions") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_CONDITIONS], value, 1);
return 1;
}
else if (string_strcasecmp (property, "position") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_POSITION], value, 1);
return 1;
}
else if (string_strcasecmp (property, "filling_top_bottom") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM], value, 1);
return 1;
}
else if (string_strcasecmp (property, "filling_left_right") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT], value, 1);
return 1;
}
else if (string_strcasecmp (property, "size") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_SIZE], value, 1);
return 1;
}
else if (string_strcasecmp (property, "size_max") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_SIZE_MAX], value, 1);
return 1;
}
else if (string_strcasecmp (property, "color_fg") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_COLOR_FG], value, 1);
gui_bar_refresh (bar);
return 1;
}
else if (string_strcasecmp (property, "color_delim") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_COLOR_DELIM], value, 1);
gui_bar_refresh (bar);
return 1;
}
else if (string_strcasecmp (property, "color_bg") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_COLOR_BG], value, 1);
gui_bar_refresh (bar);
return 1;
}
else if (string_strcasecmp (property, "separator") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_SEPARATOR],
(strcmp (value, "1") == 0) ? "on" : "off",
1);
gui_bar_refresh (bar);
return 1;
}
else if (string_strcasecmp (property, "items") == 0)
{
config_file_option_set (bar->options[GUI_BAR_OPTION_ITEMS], value, 1);
gui_bar_draw (bar);
return 1;
}
return 0;
}
/*
* Returns default items for a bar name.
*
* Default bars (input, title, status, nicklist) have default items, all other
* bars have empty default items.
*/
const char *
gui_bar_default_items (const char *bar_name)
{
int i;
static char empty_items[1] = { '\0' };
for (i = 0; gui_bar_items_default_for_bars[i][0]; i++)
{
if (string_strcasecmp (gui_bar_items_default_for_bars[i][0], bar_name) == 0)
return gui_bar_items_default_for_bars[i][1];
}
/* no default items in bar */
return empty_items;
}
/*
* Creates an option for a bar.
*
* Returns pointer to new option, NULL if error.
*/
struct t_config_option *
gui_bar_create_option (const char *bar_name, int index_option, const char *value)
{
struct t_config_option *ptr_option;
int length;
char *option_name;
ptr_option = NULL;
length = strlen (bar_name) + 1 +
strlen (gui_bar_option_string[index_option]) + 1;
option_name = malloc (length);
if (!option_name)
return NULL;
snprintf (option_name, length, "%s.%s",
bar_name, gui_bar_option_string[index_option]);
switch (index_option)
{
case GUI_BAR_OPTION_HIDDEN:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "boolean",
N_("true if bar is hidden, false if it is displayed"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_hidden, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_PRIORITY:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar priority (high number means bar displayed first)"),
NULL, 0, INT_MAX, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_priority, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_TYPE:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar type (root, window, window_active, window_inactive)"),
"root|window|window_active|window_inactive", 0, 0, value, NULL, 0,
&gui_bar_config_check_type, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_CONDITIONS:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "string",
N_("conditions to display the bar: a simple condition: "
"\"active\", \"inactive\", \"nicklist\" (window must be "
"active/inactive, buffer must have a nicklist), or an "
"expression with condition(s) (see /help eval), "
"like: \"${nicklist} && ${info:term_width} > 100\" "
"(local variables for expression are ${active}, "
"${inactive} and ${nicklist})"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_conditions, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_POSITION:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar position (bottom, top, left, right)"),
"bottom|top|left|right", 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_position, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_FILLING_TOP_BOTTOM:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar filling direction (\"horizontal\" (from left to right) "
"or \"vertical\" (from top to bottom)) when bar position is "
"top or bottom"),
"horizontal|vertical|columns_horizontal|columns_vertical",
0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_filling, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_FILLING_LEFT_RIGHT:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar filling direction (\"horizontal\" (from left to right) "
"or \"vertical\" (from top to bottom)) when bar position is "
"left or right"),
"horizontal|vertical|columns_horizontal|columns_vertical",
0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_filling, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_SIZE:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("bar size in chars (0 = auto size)"),
NULL, 0, INT_MAX, value, NULL, 0,
&gui_bar_config_check_size, NULL, NULL,
&gui_bar_config_change_size, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_SIZE_MAX:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "integer",
N_("max bar size in chars (0 = no limit)"),
NULL, 0, INT_MAX, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_size_max, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_COLOR_FG:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "color",
N_("default text color for bar"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_color, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_COLOR_DELIM:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "color",
N_("default delimiter color for bar"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_color, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_COLOR_BG:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "color",
N_("default background color for bar"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_color, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_SEPARATOR:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "boolean",
N_("separator line between bar and other bars/windows"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, NULL,
&gui_bar_config_change_separator, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_OPTION_ITEMS:
ptr_option = config_file_new_option (
weechat_config_file, weechat_config_section_bar,
option_name, "string",
N_("items of bar, they can be separated by comma (space "
"between items) or \"+\" (glued items); special syntax "
"\"@buffer:item\" can be used to force buffer used when "
"displaying the bar item"),
NULL, 0, 0, gui_bar_default_items (bar_name), value, 0,
NULL, NULL, NULL,
&gui_bar_config_change_items, NULL, NULL,
NULL, NULL, NULL);
break;
case GUI_BAR_NUM_OPTIONS:
break;
}
free (option_name);
return ptr_option;
}
/*
* Creates option for a temporary bar (when reading configuration file).
*/
void
gui_bar_create_option_temp (struct t_gui_bar *temp_bar, int index_option,
const char *value)
{
struct t_config_option *new_option;
new_option = gui_bar_create_option (temp_bar->name,
index_option,
value);
if (new_option
&& (index_option >= 0) && (index_option < GUI_BAR_NUM_OPTIONS))
{
temp_bar->options[index_option] = new_option;
}
}
/*
* Allocates and initializes new bar structure.
*
* Returns pointer to new bar, NULL if error.
*/
struct t_gui_bar *
gui_bar_alloc (const char *name)
{
struct t_gui_bar *new_bar;
int i;
new_bar = malloc (sizeof (*new_bar));
if (new_bar)
{
new_bar->name = strdup (name);
for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++)
{
new_bar->options[i] = NULL;
}
new_bar->items_count = 0;
new_bar->items_array = NULL;
new_bar->items_buffer = NULL;
new_bar->items_prefix = NULL;
new_bar->items_name = NULL;
new_bar->items_suffix = NULL;
new_bar->bar_window = NULL;
new_bar->bar_refresh_needed = 0;
new_bar->prev_bar = NULL;
new_bar->next_bar = NULL;
}
return new_bar;
}
/*
* Creates a new bar with options.
*
* Returns pointer to new bar, NULL if error.
*/
struct t_gui_bar *
gui_bar_new_with_options (const char *name,
struct t_config_option *hidden,
struct t_config_option *priority,
struct t_config_option *type,
struct t_config_option *conditions,
struct t_config_option *position,
struct t_config_option *filling_top_bottom,
struct t_config_option *filling_left_right,
struct t_config_option *size,
struct t_config_option *size_max,
struct t_config_option *color_fg,
struct t_config_option *color_delim,
struct t_config_option *color_bg,
struct t_config_option *separator,
struct t_config_option *items)
{
struct t_gui_bar *new_bar;
struct t_gui_window *ptr_win;
/* create bar */
new_bar = gui_bar_alloc (name);
if (!new_bar)
return NULL;
new_bar->options[GUI_BAR_OPTION_HIDDEN] = hidden;
new_bar->options[GUI_BAR_OPTION_PRIORITY] = priority;
new_bar->options[GUI_BAR_OPTION_TYPE] = type;
new_bar->options[GUI_BAR_OPTION_CONDITIONS] = conditions;
new_bar->options[GUI_BAR_OPTION_POSITION] = position;
new_bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM] = filling_top_bottom;
new_bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT] = filling_left_right;
new_bar->options[GUI_BAR_OPTION_SIZE] = size;
new_bar->options[GUI_BAR_OPTION_SIZE_MAX] = size_max;
new_bar->options[GUI_BAR_OPTION_COLOR_FG] = color_fg;
new_bar->options[GUI_BAR_OPTION_COLOR_DELIM] = color_delim;
new_bar->options[GUI_BAR_OPTION_COLOR_BG] = color_bg;
new_bar->options[GUI_BAR_OPTION_SEPARATOR] = separator;
new_bar->options[GUI_BAR_OPTION_ITEMS] = items;
new_bar->items_count = 0;
new_bar->items_subcount = NULL;
new_bar->items_array = NULL;
new_bar->items_buffer = NULL;
new_bar->items_prefix = NULL;
new_bar->items_name = NULL;
new_bar->items_suffix = NULL;
gui_bar_set_items_array (new_bar, CONFIG_STRING(items));
new_bar->bar_window = NULL;
new_bar->bar_refresh_needed = 1;
/* add bar to bars list */
gui_bar_insert (new_bar);
/* add window bar */
if (CONFIG_INTEGER(new_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
{
/* create only one window for bar */
gui_bar_window_new (new_bar, NULL);
gui_window_ask_refresh (1);
}
else
{
/* create bar window for all opened windows */
for (ptr_win = gui_windows; ptr_win;
ptr_win = ptr_win->next_window)
{
gui_bar_window_new (new_bar, ptr_win);
}
}
return new_bar;
}
/*
* Creates a new bar.
*
* Returns pointer to new bar, NULL if error.
*/
struct t_gui_bar *
gui_bar_new (const char *name, const char *hidden, const char *priority,
const char *type, const char *conditions, const char *position,
const char *filling_top_bottom, const char *filling_left_right,
const char *size, const char *size_max,
const char *color_fg, const char *color_delim,
const char *color_bg, const char *separators, const char *items)
{
struct t_config_option *option_hidden, *option_priority, *option_type;
struct t_config_option *option_conditions, *option_position;
struct t_config_option *option_filling_top_bottom, *option_filling_left_right;
struct t_config_option *option_size, *option_size_max;
struct t_config_option *option_color_fg, *option_color_delim;
struct t_config_option *option_color_bg, *option_separator;
struct t_config_option *option_items;
struct t_gui_bar *new_bar;
if (!name || !name[0])
return NULL;
/* it's not possible to create 2 bars with same name */
if (gui_bar_search (name))
return NULL;
/* look for type */
if (gui_bar_search_type (type) < 0)
return NULL;
/* look for position */
if (gui_bar_search_position (position) < 0)
return NULL;
option_hidden = gui_bar_create_option (name, GUI_BAR_OPTION_HIDDEN,
hidden);
option_priority = gui_bar_create_option (name, GUI_BAR_OPTION_PRIORITY,
priority);
option_type = gui_bar_create_option (name, GUI_BAR_OPTION_TYPE,
type);
option_conditions = gui_bar_create_option (name, GUI_BAR_OPTION_CONDITIONS,
conditions);
option_position = gui_bar_create_option (name, GUI_BAR_OPTION_POSITION,
position);
option_filling_top_bottom = gui_bar_create_option (name, GUI_BAR_OPTION_FILLING_TOP_BOTTOM,
filling_top_bottom);
option_filling_left_right = gui_bar_create_option (name, GUI_BAR_OPTION_FILLING_LEFT_RIGHT,
filling_left_right);
option_size = gui_bar_create_option (name, GUI_BAR_OPTION_SIZE,
size);
option_size_max = gui_bar_create_option (name, GUI_BAR_OPTION_SIZE_MAX,
size_max);
option_color_fg = gui_bar_create_option (name, GUI_BAR_OPTION_COLOR_FG,
color_fg);
option_color_delim = gui_bar_create_option (name, GUI_BAR_OPTION_COLOR_DELIM,
color_delim);
option_color_bg = gui_bar_create_option (name, GUI_BAR_OPTION_COLOR_BG,
color_bg);
option_separator = gui_bar_create_option (name, GUI_BAR_OPTION_SEPARATOR,
(config_file_string_to_boolean (separators)) ?
"on" : "off");
option_items = gui_bar_create_option (name, GUI_BAR_OPTION_ITEMS,
items);
new_bar = gui_bar_new_with_options (name, option_hidden,
option_priority, option_type,
option_conditions, option_position,
option_filling_top_bottom,
option_filling_left_right,
option_size, option_size_max,
option_color_fg, option_color_delim,
option_color_bg, option_separator,
option_items);
if (!new_bar)
{
if (option_hidden)
config_file_option_free (option_hidden, 0);
if (option_priority)
config_file_option_free (option_priority, 0);
if (option_type)
config_file_option_free (option_type, 0);
if (option_conditions)
config_file_option_free (option_conditions, 0);
if (option_position)
config_file_option_free (option_position, 0);
if (option_filling_top_bottom)
config_file_option_free (option_filling_top_bottom, 0);
if (option_filling_left_right)
config_file_option_free (option_filling_left_right, 0);
if (option_size)
config_file_option_free (option_size, 0);
if (option_size_max)
config_file_option_free (option_size_max, 0);
if (option_color_fg)
config_file_option_free (option_color_fg, 0);
if (option_color_delim)
config_file_option_free (option_color_delim, 0);
if (option_color_bg)
config_file_option_free (option_color_bg, 0);
if (option_separator)
config_file_option_free (option_separator, 0);
if (option_items)
config_file_option_free (option_items, 0);
}
return new_bar;
}
/*
* Uses temporary bars (created by reading configuration file).
*/
void
gui_bar_use_temp_bars ()
{
struct t_gui_bar *ptr_temp_bar, *next_temp_bar;
int i, num_options_ok;
for (ptr_temp_bar = gui_temp_bars; ptr_temp_bar;
ptr_temp_bar = ptr_temp_bar->next_bar)
{
num_options_ok = 0;
for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++)
{
if (!ptr_temp_bar->options[i])
{
ptr_temp_bar->options[i] = gui_bar_create_option (ptr_temp_bar->name,
i,
gui_bar_option_default[i]);
}
if (ptr_temp_bar->options[i])
num_options_ok++;
}
if (num_options_ok == GUI_BAR_NUM_OPTIONS)
{
gui_bar_new_with_options (ptr_temp_bar->name,
ptr_temp_bar->options[GUI_BAR_OPTION_HIDDEN],
ptr_temp_bar->options[GUI_BAR_OPTION_PRIORITY],
ptr_temp_bar->options[GUI_BAR_OPTION_TYPE],
ptr_temp_bar->options[GUI_BAR_OPTION_CONDITIONS],
ptr_temp_bar->options[GUI_BAR_OPTION_POSITION],
ptr_temp_bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM],
ptr_temp_bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT],
ptr_temp_bar->options[GUI_BAR_OPTION_SIZE],
ptr_temp_bar->options[GUI_BAR_OPTION_SIZE_MAX],
ptr_temp_bar->options[GUI_BAR_OPTION_COLOR_FG],
ptr_temp_bar->options[GUI_BAR_OPTION_COLOR_DELIM],
ptr_temp_bar->options[GUI_BAR_OPTION_COLOR_BG],
ptr_temp_bar->options[GUI_BAR_OPTION_SEPARATOR],
ptr_temp_bar->options[GUI_BAR_OPTION_ITEMS]);
}
else
{
for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++)
{
if (ptr_temp_bar->options[i])
{
config_file_option_free (ptr_temp_bar->options[i], 0);
ptr_temp_bar->options[i] = NULL;
}
}
}
}
/* free all temporary bars */
while (gui_temp_bars)
{
next_temp_bar = gui_temp_bars->next_bar;
if (gui_temp_bars->name)
free (gui_temp_bars->name);
free (gui_temp_bars);
gui_temp_bars = next_temp_bar;
}
last_gui_temp_bar = NULL;
}
/*
* Creates default input bar if it does not exist.
*/
void
gui_bar_create_default_input ()
{
struct t_gui_bar *ptr_bar;
int length;
char *buf;
/* search an input_text item */
if (!gui_bar_item_used_in_at_least_one_bar (gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT],
1, 0))
{
ptr_bar = gui_bar_search (GUI_BAR_DEFAULT_NAME_INPUT);
if (ptr_bar)
{
/* add item "input_text" to input bar */
length = 1;
if (CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS]))
length += strlen (CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS]));
length += 1; /* "," */
length += strlen (gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT]);
buf = malloc (length);
if (buf)
{
snprintf (buf, length, "%s,%s",
(CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS])) ?
CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS]) : "",
gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT]);
config_file_option_set (ptr_bar->options[GUI_BAR_OPTION_ITEMS], buf, 1);
gui_chat_printf (NULL, _("Bar \"%s\" updated"),
GUI_BAR_DEFAULT_NAME_INPUT);
gui_bar_draw (ptr_bar);
free (buf);
}
}
else
{
/* create input bar */
if (gui_bar_new (GUI_BAR_DEFAULT_NAME_INPUT,
"0", /* hidden */
"1000", /* priority */
"window", /* type */
"", /* conditions */
"bottom", /* position */
"horizontal", /* filling_top_bottom */
"vertical", /* filling_left_right */
"1", /* size */
"0", /* size_max */
"default", /* color fg */
"cyan", /* color delim */
"default", /* color bg */
"0", /* separators */
gui_bar_default_items (GUI_BAR_DEFAULT_NAME_INPUT))) /* items */
{
gui_chat_printf (NULL, _("Bar \"%s\" created"),
GUI_BAR_DEFAULT_NAME_INPUT);
}
}
}
}
/*
* Creates default title bar if it does not exist.
*/
void
gui_bar_create_default_title ()
{
struct t_gui_bar *ptr_bar;
/* search title bar */
ptr_bar = gui_bar_search (GUI_BAR_DEFAULT_NAME_TITLE);
if (!ptr_bar)
{
/* create title bar */
if (gui_bar_new (GUI_BAR_DEFAULT_NAME_TITLE,
"0", /* hidden */
"500", /* priority */
"window", /* type */
"", /* conditions */
"top", /* position */
"horizontal", /* filling_top_bottom */
"vertical" , /* filling_left_right */
"1", /* size */
"0", /* size_max */
"default", /* color fg */
"cyan", /* color delim */
"blue", /* color bg */
"0", /* separators */
gui_bar_default_items (GUI_BAR_DEFAULT_NAME_TITLE))) /* items */
{
gui_chat_printf (NULL, _("Bar \"%s\" created"),
GUI_BAR_DEFAULT_NAME_TITLE);
}
}
}
/*
* Creates default status bar if it does not exist.
*/
void
gui_bar_create_default_status ()
{
struct t_gui_bar *ptr_bar;
/* search status bar */
ptr_bar = gui_bar_search (GUI_BAR_DEFAULT_NAME_STATUS);
if (!ptr_bar)
{
/* create status bar */
if (gui_bar_new (GUI_BAR_DEFAULT_NAME_STATUS,
"0", /* hidden */
"500", /* priority */
"window", /* type */
"", /* conditions */
"bottom", /* position */
"horizontal", /* filling_top_bottom */
"vertical", /* filling_left_right */
"1", /* size */
"0", /* size_max */
"default", /* color fg */
"cyan", /* color delim */
"blue", /* color bg */
"0", /* separators */
gui_bar_default_items (GUI_BAR_DEFAULT_NAME_STATUS))) /* items */
{
gui_chat_printf (NULL, _("Bar \"%s\" created"),
GUI_BAR_DEFAULT_NAME_STATUS);
}
}
}
/*
* Creates default nicklist bar if it does not exist.
*/
void
gui_bar_create_default_nicklist ()
{
struct t_gui_bar *ptr_bar;
/* search nicklist bar */
ptr_bar = gui_bar_search (GUI_BAR_DEFAULT_NAME_NICKLIST);
if (!ptr_bar)
{
/* create nicklist bar */
if (gui_bar_new (GUI_BAR_DEFAULT_NAME_NICKLIST,
"0", /* hidden */
"200", /* priority */
"window", /* type */
"${nicklist}", /* conditions */
"right", /* position */
"columns_vertical", /* filling_top_bottom */
"vertical", /* filling_left_right */
"0", /* size */
"0", /* size_max */
"default", /* color fg */
"cyan", /* color delim */
"default", /* color bg */
"1", /* separators */
gui_bar_default_items (GUI_BAR_DEFAULT_NAME_NICKLIST))) /* items */
{
gui_chat_printf (NULL, _("Bar \"%s\" created"),
GUI_BAR_DEFAULT_NAME_NICKLIST);
}
}
}
/*
* Creates default bars if they do not exist.
*/
void
gui_bar_create_default ()
{
gui_bar_create_default_input ();
gui_bar_create_default_title ();
gui_bar_create_default_status ();
gui_bar_create_default_nicklist ();
}
/*
* Updates a bar on screen.
*/
void
gui_bar_update (const char *name)
{
struct t_gui_bar *ptr_bar;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN])
&& (string_strcasecmp (ptr_bar->name, name) == 0))
{
gui_bar_ask_refresh (ptr_bar);
}
}
}
/*
* Scrolls a bar.
*
* Returns:
* 1: scroll OK
* 0: error
*/
int
gui_bar_scroll (struct t_gui_bar *bar, struct t_gui_window *window,
const char *scroll)
{
struct t_gui_bar_window *ptr_bar_win;
long number;
char *str, *error;
int length, add_x, add, percent, scroll_beginning, scroll_end;
if (!bar)
return 0;
if (CONFIG_BOOLEAN(bar->options[GUI_BAR_OPTION_HIDDEN]))
return 1;
add_x = 0;
str = NULL;
number = 0;
add = 0;
percent = 0;
scroll_beginning = 0;
scroll_end = 0;
if ((scroll[0] == 'x') || (scroll[0] == 'X'))
{
add_x = 1;
scroll++;
}
else if ((scroll[0] == 'y') || (scroll[0] == 'Y'))
{
scroll++;
}
else
{
/* auto-detect if we scroll X/Y, according to filling */
if (gui_bar_get_filling (bar) == GUI_BAR_FILLING_HORIZONTAL)
add_x = 1;
}
if ((scroll[0] == 'b') || (scroll[0] == 'B'))
{
scroll_beginning = 1;
}
else if ((scroll[0] == 'e') || (scroll[0] == 'E'))
{
scroll_end = 1;
}
else
{
if (scroll[0] == '+')
{
add = 1;
scroll++;
}
else if (scroll[0] == '-')
{
scroll++;
}
else
return 0;
length = strlen (scroll);
if (length == 0)
return 0;
if (scroll[length - 1] == '%')
{
str = string_strndup (scroll, length - 1);
percent = 1;
}
else
str = strdup (scroll);
if (!str)
return 0;
error = NULL;
number = strtol (str, &error, 10);
if (!error || error[0] || (number <= 0))
{
free (str);
return 0;
}
}
if (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
{
gui_bar_window_scroll (bar->bar_window, NULL,
add_x, scroll_beginning, scroll_end,
add, percent, number);
}
else if (window)
{
for (ptr_bar_win = window->bar_windows; ptr_bar_win;
ptr_bar_win = ptr_bar_win->next_bar_window)
{
if (ptr_bar_win->bar == bar)
{
gui_bar_window_scroll (ptr_bar_win, window,
add_x, scroll_beginning, scroll_end,
add, percent, number);
}
}
}
if (str)
free (str);
return 1;
}
/*
* Deletes a bar.
*/
void
gui_bar_free (struct t_gui_bar *bar)
{
int i;
if (!bar)
return;
/* remove bar window(s) */
if (bar->bar_window)
{
gui_bar_window_free (bar->bar_window, NULL);
gui_window_ask_refresh (1);
}
else
gui_bar_free_bar_windows (bar);
/* remove bar from bars list */
if (bar->prev_bar)
(bar->prev_bar)->next_bar = bar->next_bar;
if (bar->next_bar)
(bar->next_bar)->prev_bar = bar->prev_bar;
if (gui_bars == bar)
gui_bars = bar->next_bar;
if (last_gui_bar == bar)
last_gui_bar = bar->prev_bar;
/* free data */
if (bar->name)
free (bar->name);
for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++)
{
if (bar->options[i])
config_file_option_free (bar->options[i], 1);
}
gui_bar_free_items_arrays (bar);
free (bar);
}
/*
* Deletes all bars.
*/
void
gui_bar_free_all ()
{
while (gui_bars)
{
gui_bar_free (gui_bars);
}
}
/*
* Frees bar windows for a bar.
*/
void
gui_bar_free_bar_windows (struct t_gui_bar *bar)
{
struct t_gui_window *ptr_win;
struct t_gui_bar_window *ptr_bar_win, *next_bar_win;
if (bar->bar_window)
{
gui_bar_window_free (bar->bar_window, NULL);
}
else
{
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
ptr_bar_win = ptr_win->bar_windows;
while (ptr_bar_win)
{
next_bar_win = ptr_bar_win->next_bar_window;
if (ptr_bar_win->bar == bar)
gui_bar_window_free (ptr_bar_win, ptr_win);
ptr_bar_win = next_bar_win;
}
}
}
}
/*
* Returns hdata for bar.
*/
struct t_hdata *
gui_bar_hdata_bar_cb (const void *pointer, void *data, const char *hdata_name)
{
struct t_hdata *hdata;
/* make C compiler happy */
(void) pointer;
(void) data;
hdata = hdata_new (NULL, hdata_name, "prev_bar", "next_bar",
0, 0, NULL, NULL);
if (hdata)
{
HDATA_VAR(struct t_gui_bar, name, STRING, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, options, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_count, INTEGER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_subcount, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_array, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_buffer, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_prefix, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_name, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_suffix, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, bar_window, POINTER, 0, NULL, "bar_window");
HDATA_VAR(struct t_gui_bar, bar_refresh_needed, INTEGER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, prev_bar, POINTER, 0, NULL, hdata_name);
HDATA_VAR(struct t_gui_bar, next_bar, POINTER, 0, NULL, hdata_name);
HDATA_LIST(gui_bars, WEECHAT_HDATA_LIST_CHECK_POINTERS);
HDATA_LIST(last_gui_bar, 0);
}
return hdata;
}
/*
* Adds a bar in an infolist.
*
* Returns:
* 1: OK
* 0: error
*/
int
gui_bar_add_to_infolist (struct t_infolist *infolist,
struct t_gui_bar *bar)
{
struct t_infolist_item *ptr_item;
int i, j;
char option_name[64];
if (!infolist || !bar)
return 0;
ptr_item = infolist_new_item (infolist);
if (!ptr_item)
return 0;
if (!infolist_new_var_string (ptr_item, "name", bar->name))
return 0;
if (!infolist_new_var_integer (ptr_item, "hidden", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_HIDDEN])))
return 0;
if (!infolist_new_var_integer (ptr_item, "priority", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_PRIORITY])))
return 0;
if (!infolist_new_var_integer (ptr_item, "type", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE])))
return 0;
if (!infolist_new_var_string (ptr_item, "conditions", CONFIG_STRING(bar->options[GUI_BAR_OPTION_CONDITIONS])))
return 0;
if (!infolist_new_var_integer (ptr_item, "position", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_POSITION])))
return 0;
if (!infolist_new_var_integer (ptr_item, "filling_top_bottom", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM])))
return 0;
if (!infolist_new_var_integer (ptr_item, "filling_left_right", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT])))
return 0;
if (!infolist_new_var_integer (ptr_item, "size", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_SIZE])))
return 0;
if (!infolist_new_var_integer (ptr_item, "size_max", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_SIZE_MAX])))
return 0;
if (!infolist_new_var_string (ptr_item, "color_fg", gui_color_get_name (CONFIG_COLOR(bar->options[GUI_BAR_OPTION_COLOR_FG]))))
return 0;
if (!infolist_new_var_string (ptr_item, "color_delim", gui_color_get_name (CONFIG_COLOR(bar->options[GUI_BAR_OPTION_COLOR_DELIM]))))
return 0;
if (!infolist_new_var_string (ptr_item, "color_bg", gui_color_get_name (CONFIG_COLOR(bar->options[GUI_BAR_OPTION_COLOR_BG]))))
return 0;
if (!infolist_new_var_integer (ptr_item, "separator", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_SEPARATOR])))
return 0;
if (!infolist_new_var_string (ptr_item, "items", CONFIG_STRING(bar->options[GUI_BAR_OPTION_ITEMS])))
return 0;
if (!infolist_new_var_integer (ptr_item, "items_count", bar->items_count))
return 0;
for (i = 0; i < bar->items_count; i++)
{
for (j = 0; j < bar->items_subcount[i]; j++)
{
snprintf (option_name, sizeof (option_name),
"items_array_%05d_%05d", i + 1, j + 1);
if (!infolist_new_var_string (ptr_item, option_name,
bar->items_array[i][j]))
return 0;
snprintf (option_name, sizeof (option_name),
"items_buffer_%05d_%05d", i + 1, j + 1);
if (!infolist_new_var_string (ptr_item, option_name,
bar->items_buffer[i][j]))
return 0;
snprintf (option_name, sizeof (option_name),
"items_prefix_%05d_%05d", i + 1, j + 1);
if (!infolist_new_var_string (ptr_item, option_name,
bar->items_prefix[i][j]))
return 0;
snprintf (option_name, sizeof (option_name),
"items_suffix_%05d_%05d", i + 1, j + 1);
if (!infolist_new_var_string (ptr_item, option_name,
bar->items_suffix[i][j]))
return 0;
}
}
if (!infolist_new_var_pointer (ptr_item, "bar_window", bar->bar_window))
return 0;
return 1;
}
/*
* Prints bar infos in WeeChat log file (usually for crash dump).
*/
void
gui_bar_print_log ()
{
struct t_gui_bar *ptr_bar;
int i, j;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
log_printf ("");
log_printf ("[bar (addr:0x%lx)]", ptr_bar);
log_printf (" name . . . . . . . . . : '%s'", ptr_bar->name);
log_printf (" hidden . . . . . . . . : %d", CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]));
log_printf (" priority . . . . . . . : %d", CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_PRIORITY]));
log_printf (" type . . . . . . . . . : %d (%s)",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]),
gui_bar_type_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE])]);
log_printf (" conditions . . . . . . : '%s'", CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_CONDITIONS]));
log_printf (" position . . . . . . . : %d (%s)",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_POSITION]),
gui_bar_position_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_POSITION])]);
log_printf (" filling_top_bottom . . : %d (%s)",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM]),
gui_bar_filling_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM])]);
log_printf (" filling_left_right . . : %d (%s)",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT]),
gui_bar_filling_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT])]);
log_printf (" size . . . . . . . . . : %d", CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE]));
log_printf (" size_max . . . . . . . : %d", CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SIZE_MAX]));
log_printf (" color_fg . . . . . . . : %d (%s)",
CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_FG]),
gui_color_get_name (CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_FG])));
log_printf (" color_delim. . . . . . : %d (%s)",
CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_DELIM]),
gui_color_get_name (CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_DELIM])));
log_printf (" color_bg . . . . . . . : %d (%s)",
CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_BG]),
gui_color_get_name (CONFIG_COLOR(ptr_bar->options[GUI_BAR_OPTION_COLOR_BG])));
log_printf (" separator. . . . . . . : %d", CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_SEPARATOR]));
log_printf (" items. . . . . . . . . : '%s'", CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_ITEMS]));
log_printf (" items_count. . . . . . : %d", ptr_bar->items_count);
for (i = 0; i < ptr_bar->items_count; i++)
{
log_printf (" items_subcount[%03d]. : %d",
i, ptr_bar->items_subcount[i]);
for (j = 0; j < ptr_bar->items_subcount[i]; j++)
{
log_printf (" items_array[%03d][%03d]: '%s' "
"(buffer: '%s', prefix: '%s', name: '%s', suffix: '%s')",
i, j,
ptr_bar->items_array[i][j],
ptr_bar->items_buffer[i][j],
ptr_bar->items_prefix[i][j],
ptr_bar->items_name[i][j],
ptr_bar->items_suffix[i][j]);
}
}
log_printf (" bar_window . . . . . . : 0x%lx", ptr_bar->bar_window);
log_printf (" bar_refresh_needed . . : %d", ptr_bar->bar_refresh_needed);
log_printf (" prev_bar . . . . . . . : 0x%lx", ptr_bar->prev_bar);
log_printf (" next_bar . . . . . . . : 0x%lx", ptr_bar->next_bar);
if (ptr_bar->bar_window)
gui_bar_window_print_log (ptr_bar->bar_window);
}
}