1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Merge pull request #697 from ailin-nemui/rsplit

sideways split support for Irssi
This commit is contained in:
ailin-nemui 2018-01-08 12:20:20 +01:00 committed by GitHub
commit a6663c58d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1396 additions and 357 deletions

View File

@ -35,10 +35,19 @@
SHRINK: %|Decrease the size of the active split window by the specified number of lines. 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. SIZE: %|Set the current split window size to the specified numer of lines.
BALANCE: %|Balance the heights of all split windows. 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. 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. 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. 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.
DOWN: %|Set the split window below the current one active. At the bottom, wraps to the top. 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). 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). 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. 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 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 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 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. %|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 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 { typedef struct {
char *servertag; char *servertag;
char *name; char *name;

View File

@ -480,27 +480,30 @@ int format_real_length(const char *str, int len)
start = str; start = str;
tmp = g_string_new(NULL); tmp = g_string_new(NULL);
while (*str != '\0' && len > 0) { while (*str != '\0') {
oldstr = str;
if (*str == '%' && str[1] != '\0') { if (*str == '%' && str[1] != '\0') {
str++; str++;
if (*str != '%') { if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL); adv = format_expand_styles(tmp, &str, NULL);
if (adv) {
str += adv; str += adv;
if (adv)
continue; continue;
} }
/* discount for unknown % */
/* %% or unknown %code, written as-is */ if (--len < 0) {
if (*str != '%') { str = oldstr;
if (--len == 0)
break; break;
} }
oldstr = str;
}
} }
oldstr = str;
len -= string_advance(&str, utf8); len -= string_advance(&str, utf8);
if (len < 0) if (len < 0) {
str = oldstr; str = oldstr;
break;
}
} }
g_string_free(tmp, TRUE); g_string_free(tmp, TRUE);

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); 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) static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
{ {
WINDOW_REC *window; 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); g_return_if_fail(data != NULL);
type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? 1 : type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? MAIN_WINDOW_TYPE_HIDDEN :
(g_ascii_strcasecmp(data, "split") == 0 ? 2 : 0); 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)); signal_emit("gui window create override", 1, GINT_TO_POINTER(type));
window = window_create(NULL, FALSE); 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 */ /* create new window to use */
if (settings_get_bool("autocreate_split_windows")) { if (settings_get_bool("autocreate_split_windows")) {
signal_emit("gui window create override", 1, signal_emit("gui window create override", 1,
GINT_TO_POINTER(0)); GINT_TO_POINTER(MAIN_WINDOW_TYPE_SPLIT));
} }
window = window_create(item, automatic); window = window_create(item, automatic);
} else { } else {

View File

@ -24,6 +24,7 @@
#include "formats.h" #include "formats.h"
#include "printtext.h" #include "printtext.h"
#include "themes.h"
#include "term.h" #include "term.h"
#include "gui-printtext.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); 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) static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
{ {
LINE_REC *line; 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_set_color2(root_window, attr, fg, bg);
term_move(root_window, next_xpos, next_ypos); term_move(root_window, next_xpos, next_ypos);
if (flags & GUI_PRINT_FLAG_CLRTOEOL) 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); term_clrtoeol(root_window);
}
}
next_xpos += term_addstr(root_window, str); next_xpos += term_addstr(root_window, str);
return; 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_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(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_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 #endif

View File

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

View File

@ -84,6 +84,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, "first_line", window->first_line);
iconfig_node_set_int(node, "lines", window->height); 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) static void sig_layout_save(void)
@ -98,8 +100,16 @@ static void sig_layout_save(void)
static int window_node_cmp(CONFIG_NODE *n1, CONFIG_NODE *n2) static int window_node_cmp(CONFIG_NODE *n1, CONFIG_NODE *n2)
{ {
return config_node_get_int(n1, "first_line", 0) > return (config_node_get_int(n1, "first_line", 0) ==
config_node_get_int(n2, "first_line", 0) ? -1 : 1; 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 /* Returns list of mainwindow nodes sorted by first_line
@ -118,14 +128,45 @@ static GSList *get_sorted_windows_config(CONFIG_NODE *node)
return output; 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) static void sig_layout_restore(void)
{ {
MAIN_WINDOW_REC *lower_window; MAIN_WINDOW_REC *lower_window;
WINDOW_REC *window; WINDOW_REC *window, *first;
CONFIG_NODE *node; CONFIG_NODE *node;
GSList *tmp, *sorted_config; GSList *tmp, *sorted_config, *lines_config;
int avail_height, height, *heights; int avail_height, height, *heights, *widths, max_wins_line;
int i, lower_size, windows_count, diff; int i, lower_size, lines_count, columns_count, diff;
node = iconfig_node_traverse("mainwindows", FALSE); node = iconfig_node_traverse("mainwindows", FALSE);
if (node == NULL) return; if (node == NULL) return;
@ -133,37 +174,42 @@ static void sig_layout_restore(void)
sorted_config = get_sorted_windows_config(node); sorted_config = get_sorted_windows_config(node);
if (sorted_config == NULL) return; 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 - avail_height = term_height -
screen_reserved_top - screen_reserved_bottom; screen_reserved_top - screen_reserved_bottom;
height = 0; height = 0;
heights = g_new0(int, windows_count); heights = g_new0(int, lines_count);
for (i = 0, tmp = sorted_config; tmp != NULL; tmp = tmp->next, i++) { for (i = 0, tmp = lines_config; tmp != NULL; tmp = tmp->next, i++) {
CONFIG_NODE *node = tmp->data; 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]; 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) { if (avail_height <= (WINDOW_MIN_SIZE*2)+1) {
/* we can fit only one window to screen - /* we can fit only one window to screen -
give it all the height we can */ give it all the height we can */
windows_count = 1; lines_count = 1;
heights[0] = avail_height; heights[0] = avail_height;
} else if (height != avail_height) { } else if (height != avail_height) {
/* Terminal's height is different from the saved one. /* Terminal's height is different from the saved one.
Resize the windows so they fit to screen. */ Resize the windows so they fit to screen. */
while (height > avail_height && 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, /* all windows can't fit into screen,
remove the lowest ones */ remove the lowest ones */
windows_count--; lines_count--;
} }
/* try to keep the windows' size about the same in percents */ /* try to keep the windows' size about the same in percents */
for (i = 0; i < windows_count; i++) { for (i = 0; i < lines_count; i++) {
int size = avail_height*heights[i]/height; int size = avail_height*heights[i]/height;
if (size < WINDOW_MIN_SIZE+1) if (size < WINDOW_MIN_SIZE+1)
size = WINDOW_MIN_SIZE+1; size = WINDOW_MIN_SIZE+1;
@ -172,12 +218,12 @@ static void sig_layout_restore(void)
/* give/remove the last bits */ /* give/remove the last bits */
height = 0; height = 0;
for (i = 0; i < windows_count; i++) for (i = 0; i < lines_count; i++)
height += heights[i]; height += heights[i];
diff = height < avail_height ? 1 : -1; diff = height < avail_height ? 1 : -1;
for (i = 0; height != avail_height; i++) { for (i = 0; height != avail_height; i++) {
if (i == windows_count) if (i == lines_count)
i = 0; i = 0;
if (heights[i] > WINDOW_MIN_SIZE+1) { if (heights[i] > WINDOW_MIN_SIZE+1) {
@ -188,24 +234,58 @@ static void sig_layout_restore(void)
} }
/* create all the visible windows with correct size */ /* create all the visible windows with correct size */
lower_window = NULL; lower_size = 0; lower_window = NULL; lower_size = 0; first = NULL;
for (i = 0, tmp = sorted_config; i < windows_count; tmp = tmp->next, i++) { 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; CONFIG_NODE *node = tmp->data;
if (node->key == NULL) continue; if (node->key == NULL) continue;
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 = 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 */ /* create a new window + mainwindow */
signal_emit("gui window create override", 1, signal_emit("gui window create override", 1,
GINT_TO_POINTER(0)); GINT_TO_POINTER(window == NULL ? MAIN_WINDOW_TYPE_SPLIT : MAIN_WINDOW_TYPE_RSPLIT));
window = window_create(NULL, TRUE); new_win = window_create(NULL, TRUE);
window_set_refnum(window, atoi(node->key));
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) if (lower_size > 0)
mainwindow_set_size(lower_window, lower_size, FALSE); 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]; lower_size = heights[i];
if (lower_size < WINDOW_MIN_SIZE+1) if (lower_size < WINDOW_MIN_SIZE+1)
@ -216,6 +296,11 @@ static void sig_layout_restore(void)
if (lower_size > 0) if (lower_size > 0)
mainwindow_set_size(lower_window, lower_size, FALSE); 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) static void sig_layout_reset(void)

File diff suppressed because it is too large Load Diff

View File

@ -5,10 +5,14 @@
#include "term.h" #include "term.h"
#define WINDOW_MIN_SIZE 2 #define WINDOW_MIN_SIZE 2
#define NEW_WINDOW_WIDTH 10
#define MAIN_WINDOW_TEXT_HEIGHT(window) \ #define MAIN_WINDOW_TEXT_HEIGHT(window) \
((window)->height-(window)->statusbar_lines) ((window)->height-(window)->statusbar_lines)
#define MAIN_WINDOW_TEXT_WIDTH(window) \
((window)->width-(window)->statusbar_columns)
typedef struct { typedef struct {
WINDOW_REC *active; WINDOW_REC *active;
@ -16,25 +20,33 @@ typedef struct {
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_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) */ int width, height; /* width/height of the window (includes statusbars) */
GSList *statusbars; GSList *statusbars;
int statusbar_lines_top; int statusbar_lines_top, statusbar_lines_bottom;
int statusbar_lines_bottom;
int statusbar_lines; /* top+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 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. */ unsigned int size_dirty:1; /* We'll need to resize the window, but haven't got around doing it just yet. */
} MAIN_WINDOW_REC; } MAIN_WINDOW_REC;
typedef struct {
char *color;
TERM_WINDOW *window;
} MAIN_WINDOW_BORDER_REC;
extern GSList *mainwindows; extern GSList *mainwindows;
extern MAIN_WINDOW_REC *active_mainwin; extern MAIN_WINDOW_REC *active_mainwin;
extern MAIN_WINDOW_BORDER_REC *clrtoeol_info;
extern int screen_reserved_top, screen_reserved_bottom; extern int screen_reserved_top, screen_reserved_bottom;
void mainwindows_init(void); void mainwindows_init(void);
void mainwindows_deinit(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 mainwindow_destroy(MAIN_WINDOW_REC *window);
void mainwindows_redraw(void); void mainwindows_redraw(void);
@ -45,6 +57,7 @@ void mainwindows_recreate(void);
to be resized instead of upper window. */ to be resized instead of upper window. */
void mainwindow_set_size(MAIN_WINDOW_REC *window, int height, void mainwindow_set_size(MAIN_WINDOW_REC *window, int height,
int resize_lower); int resize_lower);
void mainwindow_set_rsize(MAIN_WINDOW_REC *window, int width);
void mainwindows_resize(int width, int height); void mainwindows_resize(int width, int height);
void mainwindow_change_active(MAIN_WINDOW_REC *mainwin, 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); void mainwindows_redraw_dirty(void);
GSList *mainwindows_get_sorted(int reverse); GSList *mainwindows_get_sorted(int reverse);
GSList *mainwindows_get_line(MAIN_WINDOW_REC *rec);
#endif #endif

View File

@ -41,8 +41,8 @@ FORMAT_REC gui_text_formats[] =
{ "refnum_not_found", "Window number $0 not found", 1, { 0 } }, { "refnum_not_found", "Window number $0 not found", 1, { 0 } },
{ "window_too_small", "Not enough room to resize this window", 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_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_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 /WINDOW STICK OFF)", 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_not_sticky", "Window is not sticky", 0 },
{ "window_set_sticky", "Window set sticky", 0 }, { "window_set_sticky", "Window set sticky", 0 },
{ "window_unset_sticky", "Window is not sticky anymore", 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); rec = g_hash_table_lookup(input_entries, item->bar->config->name);
if (rec == NULL) { 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); item->size, term_type == TERM_TYPE_UTF8);
gui_entry_set_active(rec); gui_entry_set_active(rec);
g_hash_table_insert(input_entries, 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) { if (get_size_only) {
item->min_size = 2+term_width/10; int max_width;
item->max_size = term_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; 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); item->size);
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */ gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
} }

View File

@ -242,15 +242,22 @@ static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
static void statusbar_calc_item_positions(STATUSBAR_REC *bar) static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
{ {
WINDOW_REC *window;
WINDOW_REC *old_active_win; WINDOW_REC *old_active_win;
GSList *tmp, *right_items; GSList *tmp, *right_items;
int xpos, rxpos; int xpos, rxpos;
int max_width;
old_active_win = active_win; old_active_win = active_win;
if (bar->parent_window != NULL) if (bar->parent_window != NULL)
active_win = bar->parent_window->active; active_win = bar->parent_window->active;
statusbar_resize_items(bar, term_width); window = bar->parent_window != NULL
? bar->parent_window->active
: NULL;
max_width = window != NULL ? window->width : term_width;
statusbar_resize_items(bar, max_width);
/* left-aligned items */ /* left-aligned items */
xpos = 0; xpos = 0;
@ -296,7 +303,7 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
} }
} }
rxpos = term_width; rxpos = max_width;
for (tmp = right_items; tmp != NULL; tmp = tmp->next) { for (tmp = right_items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data; SBAR_ITEM_REC *rec = tmp->data;
@ -451,8 +458,13 @@ static void mainwindow_recalc_ypos(MAIN_WINDOW_REC *window, int placement)
static void sig_mainwindow_resized(MAIN_WINDOW_REC *window) static void sig_mainwindow_resized(MAIN_WINDOW_REC *window)
{ {
GSList *tmp;
mainwindow_recalc_ypos(window, STATUSBAR_TOP); mainwindow_recalc_ypos(window, STATUSBAR_TOP);
mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM); 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, 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, ' '); 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_string_free(out, TRUE);
} }
g_free(tmpstr); g_free(tmpstr);
@ -960,6 +972,25 @@ void statusbar_item_destroy(SBAR_ITEM_REC *item)
g_free(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) static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
{ {
WINDOW_REC *old_active_win; WINDOW_REC *old_active_win;
@ -971,9 +1002,12 @@ static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
active_win = bar->parent_window->active; active_win = bar->parent_window->active;
if (bar->dirty_xpos >= 0) { if (bar->dirty_xpos >= 0) {
MAIN_WINDOW_BORDER_REC *orig_border;
orig_border = set_border_info(bar);
str = g_strconcat(bar->color, "%>", NULL); 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); g_free(str);
restore_border_info(orig_border);
} }
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {

View File

@ -23,6 +23,12 @@ typedef struct SBAR_ITEM_REC SBAR_ITEM_REC;
#define STATUSBAR_VISIBLE_ACTIVE 2 #define STATUSBAR_VISIBLE_ACTIVE 2
#define STATUSBAR_VISIBLE_INACTIVE 3 #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 { typedef struct {
char *name; char *name;
GSList *config_bars; GSList *config_bars;

View File

@ -23,6 +23,7 @@
#include "term.h" #include "term.h"
#include "terminfo-core.h" #include "terminfo-core.h"
#include "fe-windows.h" #include "fe-windows.h"
#include "gui-printtext.h"
#include "utf8.h" #include "utf8.h"
#include <signal.h> #include <signal.h>
@ -285,7 +286,7 @@ void term_window_clear(TERM_WINDOW *window)
int y; int y;
terminfo_set_normal(); terminfo_set_normal();
if (window->y == 0 && window->height == term_height) { if (window->y == 0 && window->height == term_height && window->width == term_width) {
term_clear(); term_clear();
} else { } else {
for (y = 0; y < window->height; y++) { for (y = 0; y < window->height; y++) {
@ -552,7 +553,7 @@ int term_addstr(TERM_WINDOW *window, const char *str)
while (*ptr != '\0') { while (*ptr != '\0') {
tmp = g_utf8_get_char_validated(ptr, -1); tmp = g_utf8_get_char_validated(ptr, -1);
/* On utf8 error, treat as single byte and try to /* 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) { if (tmp == (gunichar)-1 || tmp == (gunichar)-2) {
len++; len++;
ptr++; ptr++;
@ -574,6 +575,18 @@ int term_addstr(TERM_WINDOW *window, const char *str)
void term_clrtoeol(TERM_WINDOW *window) void term_clrtoeol(TERM_WINDOW *window)
{ {
if (vcx < window->x) {
/* we just wrapped outside of the split, warp the cursor back into the window */
vcx += window->x;
vcmove = TRUE;
}
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 */ /* clrtoeol() doesn't necessarily understand colors */
if (last_fg == -1 && last_bg == -1 && if (last_fg == -1 && last_bg == -1 &&
(last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_ITALIC)) == 0) { (last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_ITALIC)) == 0) {
@ -589,6 +602,25 @@ void term_clrtoeol(TERM_WINDOW *window)
terminfo_move(vcx, vcy); terminfo_move(vcx, vcy);
term_lines_empty[vcy] = FALSE; term_lines_empty[vcy] = FALSE;
} }
}
}
void term_window_clrtoeol(TERM_WINDOW* window, int ypos)
{
if (ypos >= 0 && window->y + ypos != vcy) {
/* the line is already full */
return;
}
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) 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); void term_add_unichar(TERM_WINDOW *window, unichar chr);
int term_addstr(TERM_WINDOW *window, const char *str); int term_addstr(TERM_WINDOW *window, const char *str);
void term_clrtoeol(TERM_WINDOW *window); 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); void term_move_cursor(int x, int y);

View File

@ -418,9 +418,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
subline == 0 ? line->text : cache->lines[subline-1].start; subline == 0 ? line->text : cache->lines[subline-1].start;
for (;;) { for (;;) {
if (text == text_newline) { 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_set_color(view->window, ATTR_RESET);
term_clrtoeol(view->window); term_window_clrtoeol(view->window, ypos);
} }
if (first) if (first)
@ -452,7 +452,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
indented area first */ indented area first */
term_set_color(view->window, ATTR_RESET); term_set_color(view->window, ATTR_RESET);
term_move(view->window, 0, ypos); term_move(view->window, 0, ypos);
term_clrtoeol(view->window); term_window_clrtoeol(view->window, ypos);
if (indent_func != NULL) if (indent_func != NULL)
xpos = indent_func(view, line, ypos); xpos = indent_func(view, line, ypos);
@ -469,7 +469,15 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
} else { } else {
/* get the beginning of the next subline */ /* get the beginning of the next subline */
text_newline = cache->lines[subline].start; text_newline = cache->lines[subline].start;
if (view->width == term_width) {
/* ensure that links / long words are not broken */
need_move = !cache->lines[subline].continues; 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++; subline++;
@ -517,7 +525,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
} }
xpos += char_width; xpos += char_width;
if (xpos <= term_width) { if (xpos <= view->width) {
if (unichar_isprint(chr)) { if (unichar_isprint(chr)) {
if (view->utf8) if (view->utf8)
term_add_unichar(view->window, chr); term_add_unichar(view->window, chr);
@ -534,9 +542,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
text = end; 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_set_color(view->window, ATTR_RESET);
term_clrtoeol(view->window); term_window_clrtoeol(view->window, ypos);
} }
return drawcount; return drawcount;
@ -751,7 +759,7 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
term_set_color(view->window, ATTR_RESET); term_set_color(view->window, ATTR_RESET);
while (lines > 0) { while (lines > 0) {
term_move(view->window, 0, ypos); term_move(view->window, 0, ypos);
term_clrtoeol(view->window); term_window_clrtoeol(view->window, ypos);
ypos++; lines--; ypos++; lines--;
} }
} }
@ -847,6 +855,8 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
whole view */ whole view */
textbuffer_view_redraw(view); textbuffer_view_redraw(view);
} else { } else {
if (view->width == term_width) {
/* we can try to use vt100 scroll regions */
term_set_color(view->window, ATTR_RESET); term_set_color(view->window, ATTR_RESET);
term_window_scroll(view->window, realcount); term_window_scroll(view->window, realcount);
@ -858,6 +868,13 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
} }
term_refresh(view->window); term_refresh(view->window);
} else {
/* do not bother with vt400 scroll
rectangles for now, redraw the
whole view */
view->dirty = TRUE;
irssi_set_dirty();
}
} }
} }

View File

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