1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-02 06:11:11 +00:00

sideways split support for Irssi

warning:

* may be buggy

This commit adds support for sideways splits into Irssi. To that regard,
there are a number of new commands available

the "R" commands:
	/window new rsplit - make a new sideways split
	/window rshow - show an existing window to the right
	/window rgrow/rshrink/rsize/rbalance
	 - manipulate the size of your sideways split windows

the "D" commands:
	/window dup/ddown/dleft/dright
	 - navigate the windows directionally, as an alternative to
	   /window up/down that you can bind to some key
	/window move dleft/dright - the same for moving

Enjoy!
This commit is contained in:
ailin-nemui 2017-04-25 00:42:53 +02:00
parent 451019d05d
commit 4e71a1f485
18 changed files with 1373 additions and 345 deletions

View File

@ -35,10 +35,19 @@
SHRINK: %|Decrease the size of the active split window by the specified number of lines.
SIZE: %|Set the current split window size to the specified numer of lines.
BALANCE: %|Balance the heights of all split windows.
RGROW: %|Increase the width of the active split window by the specified number of columns.
RSHRINK: %|Decrease the wodth of the active split window by the specified number of columns.
RSIZE: %|Set the current split window width to the specified numer of columns.
RBALANCE: %|Balance the widths of all split windows in this line.
HIDE: %|Hides the current split window, or the split window specified by number or item name.
SHOW: %|Show the window specified by number or item name as a new split windows. It is made sticky when autostick_split_windows is turned on.
UP: %|Set the split window above the current one active. At the top, wraps to the bottom.
DOWN: %|Set the split window below the current one active. At the bottom, wraps to the top.
RSHOW: %|Show the window specified by number or item name as a new windows split to the right of the current window. It is made sticky when autostick_split_windows is turned on.
UP: %|Set the split window left or above the current one active. At the top, wraps to the bottom.
DOWN: %|Set the split window right or below the current one active. At the bottom, wraps to the top.
DUP: %|Set the split window above the current one active. At the top, wraps to the bottom.
DDOWN: %|Set the split window below the current one active. At the bottom, wraps to the top.
DLEFT: %|Set the split window left to the current one active. At the left, wraps to the right.
DRIGHT: %|Set the split window right to the current one active. At the right, wraps to the left.
LEFT: %|Go to the previous window numerically that is part of the current sticky group (or not part of any sticky group).
RIGHT: %|Go to the next window numerically that is part of the current sticky group (or not part of any sticky group).
STICK: %|Make the currently active window sticky, or stick the window specified by number to the currently visible split window. Or turn off stickyness of the currently active window or the window specified by number.
@ -46,6 +55,8 @@
MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group.
MOVE UP: %|Move the current window to the sticky group of the split window above. If no sticky group remains, the split window collapses.
MOVE DOWN: %|Move the current window to the sticky group of the split window below. If no sticky group remains, the split window collapses.
MOVE DLEFT: %|Move the current window to the sticky group of the split window to the left. If no sticky group remains, the split window collapses.
MOVE DRIGHT: %|Move the current window to the sticky group of the split window to the right. If no sticky group remains, the split window collapses.
%|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM.

View File

@ -11,6 +11,14 @@ enum {
DATA_LEVEL_HILIGHT
};
enum {
MAIN_WINDOW_TYPE_NONE = -1,
MAIN_WINDOW_TYPE_DEFAULT = 0,
MAIN_WINDOW_TYPE_HIDDEN = 1,
MAIN_WINDOW_TYPE_SPLIT = 2,
MAIN_WINDOW_TYPE_RSPLIT = 3
};
typedef struct {
char *servertag;
char *name;

View File

@ -169,7 +169,7 @@ static void cmd_window(const char *data, void *server, WI_ITEM_REC *item)
command_runsub("window", data, server, item);
}
/* SYNTAX: WINDOW NEW [HIDDEN|SPLIT] */
/* SYNTAX: WINDOW NEW [HIDDEN|SPLIT|RSPLIT] */
static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
@ -177,8 +177,9 @@ static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
g_return_if_fail(data != NULL);
type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? 1 :
(g_ascii_strcasecmp(data, "split") == 0 ? 2 : 0);
type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? MAIN_WINDOW_TYPE_HIDDEN :
g_ascii_strcasecmp(data, "split") == 0 ? MAIN_WINDOW_TYPE_SPLIT :
g_ascii_strncasecmp(data, "rs", 2) == 0 ? MAIN_WINDOW_TYPE_RSPLIT : MAIN_WINDOW_TYPE_DEFAULT;
signal_emit("gui window create override", 1, GINT_TO_POINTER(type));
window = window_create(NULL, FALSE);

View File

@ -314,7 +314,7 @@ void window_item_create(WI_ITEM_REC *item, int automatic)
/* create new window to use */
if (settings_get_bool("autocreate_split_windows")) {
signal_emit("gui window create override", 1,
GINT_TO_POINTER(0));
GINT_TO_POINTER(MAIN_WINDOW_TYPE_SPLIT));
}
window = window_create(item, automatic);
} else {

View File

@ -24,6 +24,7 @@
#include "formats.h"
#include "printtext.h"
#include "themes.h"
#include "term.h"
#include "gui-printtext.h"
@ -138,6 +139,39 @@ void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str)
gui_printtext_after_time(dest, prev, str, 0);
}
void gui_printtext_window_border(int x, int y)
{
char *v0, *v1;
int len;
if (current_theme != NULL) {
v1 = theme_format_expand(current_theme, "{window_border} ");
len = format_real_length(v1, 1);
v1[len] = '\0';
}
else {
v1 = g_strdup(" ");
}
if (*v1 == '\0') {
g_free(v1);
v1 = g_strdup(" ");
}
if (clrtoeol_info->color != NULL) {
char *color = g_strdup(clrtoeol_info->color);
len = format_real_length(color, 0);
color[len] = '\0';
v0 = g_strconcat(color, v1, NULL);
g_free(color);
g_free(v1);
} else {
v0 = v1;
}
gui_printtext(x, y, v0);
g_free(v0);
}
static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
{
LINE_REC *line;
@ -236,8 +270,13 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
term_set_color2(root_window, attr, fg, bg);
term_move(root_window, next_xpos, next_ypos);
if (flags & GUI_PRINT_FLAG_CLRTOEOL)
term_clrtoeol(root_window);
if (flags & GUI_PRINT_FLAG_CLRTOEOL) {
if (clrtoeol_info->window != NULL) {
term_window_clrtoeol_abs(clrtoeol_info->window, next_ypos);
} else {
term_clrtoeol(root_window);
}
}
next_xpos += term_addstr(root_window, str);
return;
}

View File

@ -20,5 +20,6 @@ void gui_printtext(int xpos, int ypos, const char *str);
void gui_printtext_internal(int xpos, int ypos, const char *str);
void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str);
void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time);
void gui_printtext_window_border(int xpos, int ypos);
#endif

View File

@ -73,17 +73,18 @@ static void gui_window_created(WINDOW_REC *window, void *automatic)
g_return_if_fail(window != NULL);
new_parent = window_create_override == 0 ||
window_create_override == 2 ||
new_parent = window_create_override == MAIN_WINDOW_TYPE_DEFAULT ||
window_create_override == MAIN_WINDOW_TYPE_SPLIT ||
window_create_override == MAIN_WINDOW_TYPE_RSPLIT ||
active_win == NULL || WINDOW_GUI(active_win) == NULL;
parent = !new_parent ? WINDOW_MAIN(active_win) : mainwindow_create();
parent = !new_parent ? WINDOW_MAIN(active_win) : mainwindow_create(window_create_override == MAIN_WINDOW_TYPE_RSPLIT);
if (parent == NULL) {
/* not enough space for new window, but we really can't
abort creation of the window anymore, so create hidden
window instead. */
parent = WINDOW_MAIN(active_win);
}
window_create_override = -1;
window_create_override = MAIN_WINDOW_TYPE_NONE;
if (parent->active == NULL) parent->active = window;
window->gui_data = gui_window_init(window, parent);
@ -281,13 +282,14 @@ static void read_settings(void)
void gui_windows_init(void)
{
settings_add_bool("lookandfeel", "autostick_split_windows", TRUE);
settings_add_bool("lookandfeel", "autostick_split_windows", FALSE);
settings_add_bool("lookandfeel", "autounstick_windows", TRUE);
settings_add_int("lookandfeel", "indent", 10);
settings_add_bool("lookandfeel", "indent_always", FALSE);
settings_add_bool("lookandfeel", "break_wide", FALSE);
settings_add_bool("lookandfeel", "scroll", TRUE);
window_create_override = -1;
window_create_override = MAIN_WINDOW_TYPE_NONE;
read_settings();
signal_add("gui window create override", (SIGNAL_FUNC) sig_window_create_override);

View File

@ -48,9 +48,9 @@ static void sig_layout_window_save(WINDOW_REC *window, CONFIG_NODE *node)
static void sig_layout_window_restore(WINDOW_REC *window, CONFIG_NODE *node)
{
WINDOW_REC *parent;
GUI_WINDOW_REC *gui;
GUI_WINDOW_REC *gui;
gui = WINDOW_GUI(window);
gui = WINDOW_GUI(window);
parent = window_find_refnum(config_node_get_int(node, "parent", -1));
if (parent != NULL)
@ -61,7 +61,7 @@ static void sig_layout_window_restore(WINDOW_REC *window, CONFIG_NODE *node)
if (config_node_get_str(node, "scroll", NULL) != NULL) {
gui->use_scroll = TRUE;
gui->scroll = config_node_get_bool(node, "scroll", TRUE);
textbuffer_view_set_scroll(gui->view, gui->scroll);
textbuffer_view_set_scroll(gui->view, gui->scroll);
}
}
@ -74,6 +74,8 @@ static void main_window_save(MAIN_WINDOW_REC *window, CONFIG_NODE *node)
iconfig_node_set_int(node, "first_line", window->first_line);
iconfig_node_set_int(node, "lines", window->height);
iconfig_node_set_int(node, "first_column", window->first_column);
iconfig_node_set_int(node, "columns", window->width);
}
static void sig_layout_save(void)
@ -88,8 +90,16 @@ static void sig_layout_save(void)
static int window_node_cmp(CONFIG_NODE *n1, CONFIG_NODE *n2)
{
return config_node_get_int(n1, "first_line", 0) >
config_node_get_int(n2, "first_line", 0) ? -1 : 1;
return (config_node_get_int(n1, "first_line", 0) ==
config_node_get_int(n2, "first_line", 0)
&&
config_node_get_int(n1, "first_column", 0) >
config_node_get_int(n2, "first_column", 0)
) ||
config_node_get_int(n1, "first_line", 0) >
config_node_get_int(n2, "first_line", 0)
? -1
: 1;
}
/* Returns list of mainwindow nodes sorted by first_line
@ -108,14 +118,45 @@ static GSList *get_sorted_windows_config(CONFIG_NODE *node)
return output;
}
static GSList *get_windows_config_filter_line(GSList *in)
{
GSList *tmp, *output;
output = NULL;
for (tmp = in; tmp != NULL; tmp = tmp->next) {
CONFIG_NODE *node = tmp->data;
if (config_node_get_int(node, "first_column", 0) == 0)
output = g_slist_append(output, node);
}
return output;
}
static GSList *get_windows_config_filter_column(GSList *in, int first_line, int last_line)
{
GSList *tmp, *output;
output = NULL;
for (tmp = in; tmp != NULL; tmp = tmp->next) {
int l1, l2;
CONFIG_NODE *node = tmp->data;
l1 = config_node_get_int(node, "first_line", -1);
l2 = l1 + config_node_get_int(node, "lines", 0) - 1;
if (l1 >= first_line && l2 <= last_line)
output = g_slist_prepend(output, node);
}
return output;
}
static void sig_layout_restore(void)
{
MAIN_WINDOW_REC *lower_window;
WINDOW_REC *window;
MAIN_WINDOW_REC *lower_window;
WINDOW_REC *window, *first;
CONFIG_NODE *node;
GSList *tmp, *sorted_config;
int avail_height, height, *heights;
int i, lower_size, windows_count, diff;
GSList *tmp, *sorted_config, *lines_config;
int avail_height, height, *heights, *widths, max_wins_line;
int i, lower_size, lines_count, columns_count, diff;
node = iconfig_node_traverse("mainwindows", FALSE);
if (node == NULL) return;
@ -123,51 +164,56 @@ static void sig_layout_restore(void)
sorted_config = get_sorted_windows_config(node);
if (sorted_config == NULL) return;
windows_count = g_slist_length(sorted_config);
lines_config = get_windows_config_filter_line(sorted_config);
lines_count = g_slist_length(lines_config);
/* calculate the saved terminal height */
/* calculate the saved terminal height */
avail_height = term_height -
screen_reserved_top - screen_reserved_bottom;
height = 0;
heights = g_new0(int, windows_count);
for (i = 0, tmp = sorted_config; tmp != NULL; tmp = tmp->next, i++) {
heights = g_new0(int, lines_count);
for (i = 0, tmp = lines_config; tmp != NULL; tmp = tmp->next, i++) {
CONFIG_NODE *node = tmp->data;
heights[i] = config_node_get_int(node, "lines", 0);
heights[i] = config_node_get_int(node, "lines", 0);
height += heights[i];
}
max_wins_line = (term_width + 1) / (NEW_WINDOW_WIDTH + 1);
if (max_wins_line < 1)
max_wins_line = 1;
if (avail_height <= (WINDOW_MIN_SIZE*2)+1) {
/* we can fit only one window to screen -
give it all the height we can */
windows_count = 1;
heights[0] = avail_height;
lines_count = 1;
heights[0] = avail_height;
} else if (height != avail_height) {
/* Terminal's height is different from the saved one.
Resize the windows so they fit to screen. */
while (height > avail_height &&
windows_count*(WINDOW_MIN_SIZE+1) > avail_height) {
lines_count*(WINDOW_MIN_SIZE+1) > avail_height) {
/* all windows can't fit into screen,
remove the lowest ones */
windows_count--;
lines_count--;
}
/* try to keep the windows' size about the same in percents */
for (i = 0; i < windows_count; i++) {
/* try to keep the windows' size about the same in percents */
for (i = 0; i < lines_count; i++) {
int size = avail_height*heights[i]/height;
if (size < WINDOW_MIN_SIZE+1)
size = WINDOW_MIN_SIZE+1;
size = WINDOW_MIN_SIZE+1;
heights[i] = size;
}
/* give/remove the last bits */
height = 0;
for (i = 0; i < windows_count; i++)
height += heights[i];
height = 0;
for (i = 0; i < lines_count; i++)
height += heights[i];
diff = height < avail_height ? 1 : -1;
for (i = 0; height != avail_height; i++) {
if (i == windows_count)
if (i == lines_count)
i = 0;
if (heights[i] > WINDOW_MIN_SIZE+1) {
@ -178,25 +224,59 @@ static void sig_layout_restore(void)
}
/* create all the visible windows with correct size */
lower_window = NULL; lower_size = 0;
for (i = 0, tmp = sorted_config; i < windows_count; tmp = tmp->next, i++) {
lower_window = NULL; lower_size = 0; first = NULL;
for (i = 0, tmp = lines_config; i < lines_count; tmp = tmp->next, i++) {
GSList *tmp2, *columns_config, *line;
int j, l1, l2;
CONFIG_NODE *node = tmp->data;
if (node->key == NULL) continue;
/* create a new window + mainwindow */
signal_emit("gui window create override", 1,
GINT_TO_POINTER(0));
l1 = config_node_get_int(node, "first_line", -1);
l2 = l1 + config_node_get_int(node, "lines", 0) - 1;
columns_config = get_windows_config_filter_column(sorted_config, l1, l2);
window = window_create(NULL, TRUE);
window_set_refnum(window, atoi(node->key));
window = NULL; columns_count = 0;
widths = g_new0(int, max_wins_line);
for (j = 0, tmp2 = columns_config; j < max_wins_line && tmp2 != NULL; tmp2 = tmp2->next, j++) {
int width;
WINDOW_REC *new_win;
CONFIG_NODE *node2 = tmp2->data;
if (node2->key == NULL) continue;
/* create a new window + mainwindow */
signal_emit("gui window create override", 1,
GINT_TO_POINTER(window == NULL ? MAIN_WINDOW_TYPE_SPLIT : MAIN_WINDOW_TYPE_RSPLIT));
new_win = window_create(NULL, TRUE);
window_set_refnum(new_win, atoi(node2->key));
width = config_node_get_int(node2, "columns", NEW_WINDOW_WIDTH);
widths[j] = width;
columns_count += width + (window == NULL ? 0 : 1);
if (window == NULL)
window = new_win;
if (first == NULL)
first = new_win;
window_set_active(new_win);
active_mainwin = WINDOW_MAIN(new_win);
}
if (window == NULL)
continue;
line = g_slist_reverse(mainwindows_get_line(WINDOW_MAIN(window)));
for (j = g_slist_length(line), tmp2 = line; tmp2 != NULL; tmp2 = tmp2->next, j--) {
int width = MAX(NEW_WINDOW_WIDTH, widths[j-1] * term_width / columns_count);
MAIN_WINDOW_REC *rec = tmp2->data;
mainwindow_set_rsize(rec, width);
}
g_slist_free(line);
g_free(widths);
if (lower_size > 0)
mainwindow_set_size(lower_window, lower_size, FALSE);
window_set_active(window);
active_mainwin = WINDOW_MAIN(window);
lower_window = WINDOW_MAIN(window);
lower_window = WINDOW_MAIN(window);
lower_size = heights[i];
if (lower_size < WINDOW_MIN_SIZE+1)
lower_size = WINDOW_MIN_SIZE+1;
@ -206,6 +286,11 @@ static void sig_layout_restore(void)
if (lower_size > 0)
mainwindow_set_size(lower_window, lower_size, FALSE);
if (first != NULL) {
window_set_active(first);
active_mainwin = WINDOW_MAIN(first);
}
}
static void sig_layout_reset(void)

File diff suppressed because it is too large Load Diff

View File

@ -5,36 +5,48 @@
#include "term.h"
#define WINDOW_MIN_SIZE 2
#define NEW_WINDOW_WIDTH 10
#define MAIN_WINDOW_TEXT_HEIGHT(window) \
((window)->height-(window)->statusbar_lines)
#define MAIN_WINDOW_TEXT_WIDTH(window) \
((window)->width-(window)->statusbar_columns)
typedef struct {
WINDOW_REC *active;
TERM_WINDOW *screen_win;
int sticky_windows; /* number of sticky windows */
int sticky_windows; /* number of sticky windows */
int first_line, last_line; /* first/last line used by this window (0..x) (includes statusbars) */
int first_column, last_column; /* first/last column used by this window (0..x) (includes statusbars) */
int width, height; /* width/height of the window (includes statusbars) */
GSList *statusbars;
int statusbar_lines_top;
int statusbar_lines_bottom;
int statusbar_lines_top, statusbar_lines_bottom;
int statusbar_lines; /* top+bottom */
int statusbar_columns_left, statusbar_columns_right;
int statusbar_columns; /* left+right */
unsigned int dirty:1; /* This window needs a redraw */
unsigned int size_dirty:1; /* We'll need to resize the window, but haven't got around doing it just yet. */
} MAIN_WINDOW_REC;
typedef struct {
char *color;
TERM_WINDOW *window;
} MAIN_WINDOW_BORDER_REC;
extern GSList *mainwindows;
extern MAIN_WINDOW_REC *active_mainwin;
extern MAIN_WINDOW_BORDER_REC *clrtoeol_info;
extern int screen_reserved_top, screen_reserved_bottom;
void mainwindows_init(void);
void mainwindows_deinit(void);
MAIN_WINDOW_REC *mainwindow_create(void);
MAIN_WINDOW_REC *mainwindow_create(int);
void mainwindow_destroy(MAIN_WINDOW_REC *window);
void mainwindows_redraw(void);
@ -45,6 +57,7 @@ void mainwindows_recreate(void);
to be resized instead of upper window. */
void mainwindow_set_size(MAIN_WINDOW_REC *window, int height,
int resize_lower);
void mainwindow_set_rsize(MAIN_WINDOW_REC *window, int width);
void mainwindows_resize(int width, int height);
void mainwindow_change_active(MAIN_WINDOW_REC *mainwin,
@ -56,5 +69,6 @@ int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window,
void mainwindows_redraw_dirty(void);
GSList *mainwindows_get_sorted(int reverse);
GSList *mainwindows_get_line(MAIN_WINDOW_REC *rec);
#endif

View File

@ -41,8 +41,8 @@ FORMAT_REC gui_text_formats[] =
{ "refnum_not_found", "Window number $0 not found", 1, { 0 } },
{ "window_too_small", "Not enough room to resize this window", 0 },
{ "cant_hide_last", "You can't hide the last window", 0 },
{ "cant_hide_sticky_windows", "You can't hide sticky windows (use /WINDOW STICK OFF)", 0 },
{ "cant_show_sticky_windows", "You can't show sticky windows (use /WINDOW STICK OFF)", 0 },
{ "cant_hide_sticky_windows", "You can't hide sticky windows (use /SET autounstick_windows ON)", 0 },
{ "cant_show_sticky_windows", "You can't show sticky windows (use /SET autounstick_windows ON)", 0 },
{ "window_not_sticky", "Window is not sticky", 0 },
{ "window_set_sticky", "Window set sticky", 0 },
{ "window_unset_sticky", "Window is not sticky anymore", 0 },

View File

@ -418,7 +418,7 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
rec = g_hash_table_lookup(input_entries, item->bar->config->name);
if (rec == NULL) {
rec = gui_entry_create(item->xpos, item->bar->real_ypos,
rec = gui_entry_create(ITEM_WINDOW_REAL_XPOS(item), item->bar->real_ypos,
item->size, term_type == TERM_TYPE_UTF8);
gui_entry_set_active(rec);
g_hash_table_insert(input_entries,
@ -426,12 +426,21 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
}
if (get_size_only) {
item->min_size = 2+term_width/10;
item->max_size = term_width;
return;
int max_width;
WINDOW_REC *window;
window = item->bar->parent_window != NULL
? item->bar->parent_window->active
: NULL;
max_width = window != NULL ? window->width : term_width;
item->min_size = 2+max_width/10;
item->max_size = max_width;
return;
}
gui_entry_move(rec, item->xpos, item->bar->real_ypos,
gui_entry_move(rec, ITEM_WINDOW_REAL_XPOS(item), item->bar->real_ypos,
item->size);
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
}

View File

@ -242,17 +242,24 @@ static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
{
WINDOW_REC *old_active_win;
WINDOW_REC *window;
WINDOW_REC *old_active_win;
GSList *tmp, *right_items;
int xpos, rxpos;
int max_width;
old_active_win = active_win;
if (bar->parent_window != NULL)
if (bar->parent_window != NULL)
active_win = bar->parent_window->active;
statusbar_resize_items(bar, term_width);
window = bar->parent_window != NULL
? bar->parent_window->active
: NULL;
/* left-aligned items */
max_width = window != NULL ? window->width : term_width;
statusbar_resize_items(bar, max_width);
/* left-aligned items */
xpos = 0;
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data;
@ -260,11 +267,11 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
if (!rec->config->right_alignment &&
(rec->size > 0 || rec->current_size > 0)) {
if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
/* redraw the item */
/* redraw the item */
rec->dirty = TRUE;
if (bar->dirty_xpos == -1 ||
xpos < bar->dirty_xpos) {
irssi_set_dirty();
irssi_set_dirty();
bar->dirty = TRUE;
bar->dirty_xpos = xpos;
}
@ -277,12 +284,12 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
/* right-aligned items - first copy them to a new list backwards,
easier to draw them in right order */
right_items = NULL;
right_items = NULL;
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data;
if (rec->config->right_alignment) {
if (rec->size > 0)
if (rec->size > 0)
right_items = g_slist_prepend(right_items, rec);
else if (rec->current_size > 0 &&
(bar->dirty_xpos == -1 ||
@ -291,12 +298,12 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
to begin from the item's old xpos */
irssi_set_dirty();
bar->dirty = TRUE;
bar->dirty_xpos = rec->xpos;
bar->dirty_xpos = rec->xpos;
}
}
}
rxpos = term_width;
rxpos = max_width;
for (tmp = right_items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data;
@ -312,7 +319,7 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
rec->xpos = rxpos;
}
}
g_slist_free(right_items);
g_slist_free(right_items);
active_win = old_active_win;
}
@ -451,8 +458,13 @@ static void mainwindow_recalc_ypos(MAIN_WINDOW_REC *window, int placement)
static void sig_mainwindow_resized(MAIN_WINDOW_REC *window)
{
mainwindow_recalc_ypos(window, STATUSBAR_TOP);
mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM);
GSList *tmp;
mainwindow_recalc_ypos(window, STATUSBAR_TOP);
mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM);
for (tmp = window->statusbars; tmp != NULL; tmp = tmp->next) {
STATUSBAR_REC *bar = tmp->data;
statusbar_redraw(bar, TRUE);
}
}
STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group,
@ -728,7 +740,7 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
g_string_append_c(out, ' ');
}
gui_printtext(item->xpos, item->bar->real_ypos, out->str);
gui_printtext(ITEM_WINDOW_REAL_XPOS(item), item->bar->real_ypos, out->str);
g_string_free(out, TRUE);
}
g_free(tmpstr);
@ -960,20 +972,42 @@ void statusbar_item_destroy(SBAR_ITEM_REC *item)
g_free(item);
}
static MAIN_WINDOW_BORDER_REC *set_border_info(STATUSBAR_REC *bar)
{
MAIN_WINDOW_BORDER_REC *orig_border, *new_border;
orig_border = clrtoeol_info;
new_border = g_new0(MAIN_WINDOW_BORDER_REC, 1);
new_border->window = bar->parent_window != NULL ? bar->parent_window->screen_win : NULL;
new_border->color = bar->color;
clrtoeol_info = new_border;
return orig_border;
}
static void restore_border_info(MAIN_WINDOW_BORDER_REC *border_info)
{
MAIN_WINDOW_BORDER_REC *old_border;
old_border = clrtoeol_info;
clrtoeol_info = border_info;
g_free(old_border);
}
static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
{
WINDOW_REC *old_active_win;
WINDOW_REC *old_active_win;
GSList *tmp;
char *str;
old_active_win = active_win;
if (bar->parent_window != NULL)
if (bar->parent_window != NULL)
active_win = bar->parent_window->active;
if (bar->dirty_xpos >= 0) {
MAIN_WINDOW_BORDER_REC *orig_border;
orig_border = set_border_info(bar);
str = g_strconcat(bar->color, "%>", NULL);
gui_printtext(bar->dirty_xpos, bar->real_ypos, str);
gui_printtext(BAR_WINDOW_REAL_DIRTY_XPOS(bar), bar->real_ypos, str);
g_free(str);
restore_border_info(orig_border);
}
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
@ -982,13 +1016,13 @@ static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
if (rec->dirty ||
(bar->dirty_xpos != -1 &&
rec->xpos >= bar->dirty_xpos)) {
rec->current_size = rec->size;
rec->current_size = rec->size;
rec->func(rec, FALSE);
rec->dirty = FALSE;
}
}
active_win = old_active_win;
active_win = old_active_win;
}
void statusbar_redraw_dirty(void)

View File

@ -23,6 +23,12 @@ typedef struct SBAR_ITEM_REC SBAR_ITEM_REC;
#define STATUSBAR_VISIBLE_ACTIVE 2
#define STATUSBAR_VISIBLE_INACTIVE 3
#define ITEM_WINDOW_REAL_XPOS(item) ( ( (item)->bar->parent_window != NULL ? \
(item)->bar->parent_window->first_column + (item)->bar->parent_window->statusbar_columns_left : 0 ) + (item)->xpos )
#define BAR_WINDOW_REAL_DIRTY_XPOS(bar) ( ( (bar)->parent_window != NULL ? \
(bar)->parent_window->first_column + (bar)->parent_window->statusbar_columns_left : 0 ) + (bar)->dirty_xpos )
typedef struct {
char *name;
GSList *config_bars;

View File

@ -23,6 +23,7 @@
#include "term.h"
#include "terminfo-core.h"
#include "fe-windows.h"
#include "gui-printtext.h"
#include "utf8.h"
#include <signal.h>
@ -284,10 +285,10 @@ void term_window_clear(TERM_WINDOW *window)
{
int y;
terminfo_set_normal();
if (window->y == 0 && window->height == term_height) {
term_clear();
} else {
terminfo_set_normal();
if (window->y == 0 && window->height == term_height && window->width == term_width) {
term_clear();
} else {
for (y = 0; y < window->height; y++) {
term_move(window, 0, y);
term_clrtoeol(window);
@ -452,14 +453,14 @@ void term_set_color(TERM_WINDOW *window, int col)
void term_move(TERM_WINDOW *window, int x, int y)
{
if (x >= 0 && y >= 0) {
vcmove = TRUE;
vcx = x+window->x;
vcy = y+window->y;
vcmove = TRUE;
vcx = x+window->x;
vcy = y+window->y;
if (vcx >= term_width)
vcx = term_width-1;
if (vcy >= term_height)
vcy = term_height-1;
if (vcx >= term_width)
vcx = term_width-1;
if (vcy >= term_height)
vcy = term_height-1;
}
}
@ -552,7 +553,7 @@ int term_addstr(TERM_WINDOW *window, const char *str)
while (*ptr != '\0') {
tmp = g_utf8_get_char_validated(ptr, -1);
/* On utf8 error, treat as single byte and try to
continue interpretting rest of string as utf8 */
continue interpreting rest of string as utf8 */
if (tmp == (gunichar)-1 || tmp == (gunichar)-2) {
len++;
ptr++;
@ -574,21 +575,47 @@ int term_addstr(TERM_WINDOW *window, const char *str)
void term_clrtoeol(TERM_WINDOW *window)
{
/* clrtoeol() doesn't necessarily understand colors */
if (last_fg == -1 && last_bg == -1 &&
(last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_ITALIC)) == 0) {
if (!term_lines_empty[vcy]) {
if (vcmove) term_move_real();
terminfo_clrtoeol();
if (vcx == 0) term_lines_empty[vcy] = TRUE;
}
} else if (vcx < term_width) {
/* we'll need to fill the line ourself. */
if (vcmove) term_move_real();
terminfo_repeat(' ', term_width-vcx);
terminfo_move(vcx, vcy);
term_lines_empty[vcy] = FALSE;
if (vcx < window->x) {
/* we just wrapped outside of the split, put the cursor back into the window */
vcx += window->x;
}
if (window->x + window->width < term_width) {
/* we need to fill a vertical split */
if (vcmove) term_move_real();
terminfo_repeat(' ', window->x + window->width - vcx + 1);
terminfo_move(vcx, vcy);
term_lines_empty[vcy] = FALSE;
} else {
/* clrtoeol() doesn't necessarily understand colors */
if (last_fg == -1 && last_bg == -1 &&
(last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_ITALIC)) == 0) {
if (!term_lines_empty[vcy]) {
if (vcmove) term_move_real();
terminfo_clrtoeol();
if (vcx == 0) term_lines_empty[vcy] = TRUE;
}
} else if (vcx < term_width) {
/* we'll need to fill the line ourself. */
if (vcmove) term_move_real();
terminfo_repeat(' ', term_width-vcx);
terminfo_move(vcx, vcy);
term_lines_empty[vcy] = FALSE;
}
}
}
void term_window_clrtoeol(TERM_WINDOW* window, int ypos)
{
term_clrtoeol(window);
if (window->x + window->width < term_width) {
gui_printtext_window_border(window->x + window->width, window->y + ypos);
term_set_color(window, ATTR_RESET);
}
}
void term_window_clrtoeol_abs(TERM_WINDOW* window, int ypos)
{
term_window_clrtoeol(window, ypos - window->y);
}
void term_move_cursor(int x, int y)

View File

@ -85,6 +85,8 @@ void term_addch(TERM_WINDOW *window, char chr);
void term_add_unichar(TERM_WINDOW *window, unichar chr);
int term_addstr(TERM_WINDOW *window, const char *str);
void term_clrtoeol(TERM_WINDOW *window);
void term_window_clrtoeol(TERM_WINDOW* window, int ypos);
void term_window_clrtoeol_abs(TERM_WINDOW* window, int ypos_abs);
void term_move_cursor(int x, int y);

View File

@ -388,9 +388,9 @@ static void view_reset_cache(TEXT_BUFFER_VIEW_REC *view)
static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
int subline, int ypos, int max)
{
INDENT_FUNC indent_func;
INDENT_FUNC indent_func;
LINE_CACHE_REC *cache;
const unsigned char *text, *end, *text_newline;
const unsigned char *text, *end, *text_newline;
unsigned char *tmp;
unichar chr;
int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width;
@ -399,54 +399,54 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
#endif
if (view->dirty) /* don't bother drawing anything - redraw is coming */
return 0;
return 0;
cache = textbuffer_view_get_line_cache(view, line);
if (subline >= cache->count)
return 0;
return 0;
color = ATTR_RESET;
need_move = TRUE; need_clrtoeol = FALSE;
color = ATTR_RESET;
need_move = TRUE; need_clrtoeol = FALSE;
xpos = drawcount = 0; first = TRUE;
text_newline = text =
subline == 0 ? line->text : cache->lines[subline-1].start;
for (;;) {
if (text == text_newline) {
if (need_clrtoeol && xpos < term_width) {
if (need_clrtoeol && xpos < view->width + (view->width == term_width ? 0 : 1)) {
term_set_color(view->window, ATTR_RESET);
term_clrtoeol(view->window);
term_window_clrtoeol(view->window, ypos);
}
if (first)
first = FALSE;
else {
ypos++;
if (--max == 0)
if (--max == 0)
break;
}
if (subline > 0) {
/* continuing previous line - indent it */
/* continuing previous line - indent it */
indent_func = cache->lines[subline-1].indent_func;
if (indent_func == NULL)
xpos = cache->lines[subline-1].indent;
color = cache->lines[subline-1].color;
color = cache->lines[subline-1].color;
#ifdef TERM_TRUECOLOR
fg24 = cache->lines[subline-1].fg24;
bg24 = cache->lines[subline-1].bg24;
fg24 = cache->lines[subline-1].fg24;
bg24 = cache->lines[subline-1].bg24;
#endif
} else {
indent_func = NULL;
}
if (xpos == 0 && indent_func == NULL)
need_clrtoeol = TRUE;
need_clrtoeol = TRUE;
else {
/* line was indented - need to clear the
indented area first */
indented area first */
term_set_color(view->window, ATTR_RESET);
term_move(view->window, 0, ypos);
term_clrtoeol(view->window);
term_window_clrtoeol(view->window, ypos);
if (indent_func != NULL)
xpos = indent_func(view, line, ypos);
@ -463,9 +463,17 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
} else {
/* get the beginning of the next subline */
text_newline = cache->lines[subline].start;
need_move = !cache->lines[subline].continues;
if (view->width == term_width) {
/* ensure that links / long words are not broken */
need_move = !cache->lines[subline].continues;
} else {
/* we cannot use the need_move
optimisation unless the split spans
the whole width */
need_move = TRUE;
}
}
drawcount++;
drawcount++;
subline++;
}
@ -473,10 +481,10 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
/* command */
text++;
if (*text == LINE_CMD_EOL)
break;
break;
if (*text == LINE_CMD_CONTINUE) {
/* jump to next block */
/* jump to next block */
memcpy(&tmp, text+1, sizeof(unsigned char *));
text = tmp;
continue;
@ -511,13 +519,13 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
}
xpos += char_width;
if (xpos <= term_width) {
if (xpos <= view->width) {
if (unichar_isprint(chr)) {
if (view->utf8)
term_add_unichar(view->window, chr);
term_add_unichar(view->window, chr);
else
for (; text < end; text++)
term_addch(view->window, *text);
for (; text < end; text++)
term_addch(view->window, *text);
} else {
/* low-ascii */
term_set_color(view->window, ATTR_RESET|ATTR_REVERSE);
@ -528,12 +536,12 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
text = end;
}
if (need_clrtoeol && xpos < term_width) {
if (need_clrtoeol && xpos < view->width + (view->width == term_width ? 0 : 1)) {
term_set_color(view->window, ATTR_RESET);
term_clrtoeol(view->window);
term_window_clrtoeol(view->window, ypos);
}
return drawcount;
return drawcount;
}
/* Recalculate view's bottom line information - try to keep the
@ -738,7 +746,7 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
term_set_color(view->window, ATTR_RESET);
while (lines > 0) {
term_move(view->window, 0, ypos);
term_clrtoeol(view->window);
term_window_clrtoeol(view->window, ypos);
ypos++; lines--;
}
}
@ -775,51 +783,51 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
int linecount, realcount, scroll_visible;
if (*lines == NULL)
return 0;
return 0;
/* scroll down */
scroll_visible = lines == &view->startline;
realcount = -*subline;
scrollcount += *subline;
*subline = 0;
*subline = 0;
while (scrollcount > 0) {
linecount = view_get_linecount(view, *lines);
if ((scroll_visible && *lines == view->bottom_startline) &&
(scrollcount >= view->bottom_subline)) {
*subline = view->bottom_subline;
realcount += view->bottom_subline;
scrollcount = 0;
break;
realcount += view->bottom_subline;
scrollcount = 0;
break;
}
realcount += linecount;
realcount += linecount;
scrollcount -= linecount;
if (scrollcount < 0) {
realcount += scrollcount;
realcount += scrollcount;
*subline = linecount+scrollcount;
scrollcount = 0;
break;
scrollcount = 0;
break;
}
if ((*lines)->next == NULL)
break;
*lines = (*lines)->next;
*lines = (*lines)->next;
}
/* scroll up */
/* scroll up */
while (scrollcount < 0 && (*lines)->prev != NULL) {
*lines = (*lines)->prev;
linecount = view_get_linecount(view, *lines);
realcount -= linecount;
realcount -= linecount;
scrollcount += linecount;
if (scrollcount > 0) {
realcount += scrollcount;
realcount += scrollcount;
*subline = scrollcount;
break;
break;
}
}
@ -827,19 +835,27 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
if (realcount <= -view->height || realcount >= view->height) {
/* scrolled more than screenful, redraw the
whole view */
textbuffer_view_redraw(view);
textbuffer_view_redraw(view);
} else {
term_set_color(view->window, ATTR_RESET);
term_window_scroll(view->window, realcount);
if (view->width == term_width) {
/* we can try to use vt100 scroll regions */
term_set_color(view->window, ATTR_RESET);
term_window_scroll(view->window, realcount);
if (draw_nonclean) {
if (realcount < 0)
view_draw_top(view, -realcount, TRUE);
else
view_draw_bottom(view, realcount);
if (draw_nonclean) {
if (realcount < 0)
view_draw_top(view, -realcount, TRUE);
else
view_draw_bottom(view, realcount);
}
term_refresh(view->window);
} else {
/* do not bother with vt400 scroll
rectangles for now, redraw the
whole view */
textbuffer_view_redraw(view);
}
term_refresh(view->window);
}
}

View File

@ -251,6 +251,7 @@ abstracts = {
# default background for all statusbars. You can also give
# the default foreground color for statusbar items.
sb_background = "%4%w";
window_border = "%4%w";
# default backround for "default" statusbar group
#sb_default_bg = "%4";