mirror of
https://github.com/irssi/irssi.git
synced 2024-10-27 05:20:20 -04:00
Redrawing fixes - irssi should now rarely redraw stuff uselessly in screen.
Most of the code now just marks the window/statusbar/etc. as dirty, and lets the dirty-checker handle it later. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1926 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
44b12481d6
commit
fb439b5c2a
@ -54,6 +54,9 @@ void gui_entry_destroy(GUI_ENTRY_REC *entry)
|
||||
/* Fixes the cursor position in screen */
|
||||
static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
|
||||
{
|
||||
int old_scrstart;
|
||||
|
||||
old_scrstart = entry->scrstart;
|
||||
if (entry->pos - entry->scrstart < entry->width-2 - entry->promptlen &&
|
||||
entry->pos - entry->scrstart > 0) {
|
||||
entry->scrpos = entry->pos - entry->scrstart;
|
||||
@ -64,6 +67,9 @@ static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
|
||||
entry->scrpos = (entry->width - entry->promptlen)*2/3;
|
||||
entry->scrstart = entry->pos - entry->scrpos;
|
||||
}
|
||||
|
||||
if (old_scrstart != entry->scrstart)
|
||||
entry->redraw_needed_from = 0;
|
||||
}
|
||||
|
||||
static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
|
||||
@ -102,15 +108,28 @@ static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
|
||||
xpos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_entry_draw(GUI_ENTRY_REC *entry)
|
||||
{
|
||||
if (entry->redraw_needed_from >= 0) {
|
||||
gui_entry_draw_from(entry, entry->redraw_needed_from);
|
||||
entry->redraw_needed_from = -1;
|
||||
}
|
||||
|
||||
term_move_cursor(entry->xpos + entry->scrpos + entry->promptlen,
|
||||
entry->ypos);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
|
||||
static void gui_entry_draw(GUI_ENTRY_REC *entry)
|
||||
static void gui_entry_redraw_from(GUI_ENTRY_REC *entry, int pos)
|
||||
{
|
||||
gui_entry_draw_from(entry, 0);
|
||||
pos -= entry->scrstart;
|
||||
if (pos < 0) pos = 0;
|
||||
|
||||
if (entry->redraw_needed_from == -1 ||
|
||||
entry->redraw_needed_from > pos)
|
||||
entry->redraw_needed_from = pos;
|
||||
}
|
||||
|
||||
void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width)
|
||||
@ -135,7 +154,7 @@ void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width)
|
||||
/* input line grew - need to draw text at the end */
|
||||
old_width = width;
|
||||
entry->width = width;
|
||||
gui_entry_draw_from(entry, old_width);
|
||||
gui_entry_redraw_from(entry, old_width);
|
||||
} else {
|
||||
/* input line shrinked - make sure the cursor
|
||||
is inside the input line */
|
||||
@ -143,9 +162,10 @@ void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width)
|
||||
if (entry->pos - entry->scrstart >
|
||||
entry->width-2 - entry->promptlen) {
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
}
|
||||
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
|
||||
void gui_entry_set_active(GUI_ENTRY_REC *entry)
|
||||
@ -196,6 +216,7 @@ void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str)
|
||||
g_string_assign(entry->text, str);
|
||||
entry->pos = entry->text->len;
|
||||
|
||||
gui_entry_redraw_from(entry, 0);
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
@ -212,6 +233,7 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
|
||||
g_return_if_fail(entry != NULL);
|
||||
g_return_if_fail(str != NULL);
|
||||
|
||||
gui_entry_redraw_from(entry, entry->pos);
|
||||
g_string_insert(entry->text, entry->pos, str);
|
||||
entry->pos += strlen(str);
|
||||
|
||||
@ -226,6 +248,7 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
|
||||
if (chr == 0)
|
||||
return; /* never insert NUL characters */
|
||||
|
||||
gui_entry_redraw_from(entry, entry->pos);
|
||||
g_string_insert_c(entry->text, entry->pos, chr);
|
||||
entry->pos++;
|
||||
|
||||
@ -249,6 +272,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
|
||||
entry->pos -= size;
|
||||
g_string_erase(entry->text, entry->pos, size);
|
||||
|
||||
gui_entry_redraw_from(entry, entry->pos);
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
@ -279,6 +303,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
|
||||
g_string_erase(entry->text, to, entry->pos - to);
|
||||
entry->pos = to;
|
||||
|
||||
gui_entry_redraw_from(entry, entry->pos);
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
@ -306,6 +331,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
|
||||
|
||||
g_string_erase(entry->text, entry->pos, to - entry->pos);
|
||||
|
||||
gui_entry_redraw_from(entry, entry->pos);
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
@ -412,6 +438,7 @@ void gui_entry_redraw(GUI_ENTRY_REC *entry)
|
||||
g_return_if_fail(entry != NULL);
|
||||
|
||||
gui_entry_set_prompt(entry, NULL);
|
||||
gui_entry_redraw_from(entry, 0);
|
||||
gui_entry_fix_cursor(entry);
|
||||
gui_entry_draw(entry);
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ typedef struct {
|
||||
int hidden; /* print the chars as spaces in input line (useful for passwords) */
|
||||
|
||||
int promptlen;
|
||||
char *prompt;
|
||||
char *prompt;
|
||||
|
||||
int redraw_needed_from;
|
||||
} GUI_ENTRY_REC;
|
||||
|
||||
extern GUI_ENTRY_REC *active_entry;
|
||||
|
@ -117,8 +117,14 @@ void gui_window_resize(WINDOW_REC *window, int width, int height)
|
||||
{
|
||||
GUI_WINDOW_REC *gui;
|
||||
|
||||
if (window->width == width && window->height == height)
|
||||
return;
|
||||
|
||||
gui = WINDOW_GUI(window);
|
||||
|
||||
irssi_set_dirty();
|
||||
WINDOW_MAIN(window)->dirty = TRUE;
|
||||
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
textbuffer_view_resize(gui->view, width, height);
|
||||
@ -248,14 +254,16 @@ static void signal_window_changed(WINDOW_REC *window)
|
||||
gui_window_reparent(window, active_mainwin);
|
||||
}
|
||||
|
||||
old_window = active_mainwin->active;
|
||||
if (old_window != NULL)
|
||||
textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL);
|
||||
old_window = active_mainwin->active;
|
||||
if (old_window != NULL && old_window != window)
|
||||
textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL);
|
||||
|
||||
active_mainwin->active = window;
|
||||
|
||||
textbuffer_view_set_window(WINDOW_GUI(window)->view,
|
||||
parent->screen_win);
|
||||
if (WINDOW_GUI(window)->view->dirty)
|
||||
active_mainwin->dirty = TRUE;
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
|
@ -69,6 +69,8 @@ void mainwindow_activity_deinit(void);
|
||||
void mainwindows_layout_init(void);
|
||||
void mainwindows_layout_deinit(void);
|
||||
|
||||
static int dirty, full_redraw;
|
||||
|
||||
static GMainLoop *main_loop;
|
||||
int quitting;
|
||||
|
||||
@ -85,19 +87,43 @@ static int display_firsttimer = FALSE;
|
||||
|
||||
static void sig_exit(void)
|
||||
{
|
||||
g_main_quit(main_loop);
|
||||
quitting = TRUE;
|
||||
}
|
||||
|
||||
/* redraw irssi's screen.. */
|
||||
void irssi_redraw(void)
|
||||
{
|
||||
term_clear();
|
||||
dirty = TRUE;
|
||||
full_redraw = TRUE;
|
||||
}
|
||||
|
||||
void irssi_set_dirty(void)
|
||||
{
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
static void dirty_check(void)
|
||||
{
|
||||
if (!dirty)
|
||||
return;
|
||||
|
||||
if (full_redraw) {
|
||||
full_redraw = FALSE;
|
||||
|
||||
/* first clear the screen so curses will be
|
||||
forced to redraw the screen */
|
||||
term_clear();
|
||||
term_refresh(NULL);
|
||||
|
||||
mainwindows_redraw();
|
||||
statusbar_redraw(NULL, TRUE);
|
||||
}
|
||||
|
||||
mainwindows_redraw_dirty();
|
||||
statusbar_redraw_dirty();
|
||||
term_refresh(NULL);
|
||||
|
||||
/* windows */
|
||||
mainwindows_redraw();
|
||||
/* statusbar */
|
||||
statusbar_redraw(NULL);
|
||||
dirty = FALSE;
|
||||
}
|
||||
|
||||
static void textui_init(void)
|
||||
@ -152,7 +178,6 @@ static void textui_finish_init(void)
|
||||
|
||||
static void textui_deinit(void)
|
||||
{
|
||||
quitting = TRUE;
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
term_refresh_freeze();
|
||||
@ -164,6 +189,7 @@ static void textui_deinit(void)
|
||||
fe_perl_deinit();
|
||||
#endif
|
||||
|
||||
dirty_check(); /* one last time to print any quit messages */
|
||||
signal_remove("gui exit", (SIGNAL_FUNC) sig_exit);
|
||||
|
||||
lastlog_deinit();
|
||||
@ -256,6 +282,7 @@ static void winsock_init(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
quitting = FALSE;
|
||||
core_init_paths(argc, argv);
|
||||
|
||||
check_files();
|
||||
@ -279,7 +306,14 @@ int main(int argc, char **argv)
|
||||
|
||||
textui_finish_init();
|
||||
main_loop = g_main_new(TRUE);
|
||||
g_main_run(main_loop);
|
||||
|
||||
/* Does the same as g_main_run(main_loop), except we
|
||||
can call our dirty-checker after each iteration */
|
||||
while (!quitting) {
|
||||
g_main_iteration(TRUE);
|
||||
dirty_check();
|
||||
}
|
||||
|
||||
g_main_destroy(main_loop);
|
||||
textui_deinit();
|
||||
|
||||
|
@ -75,10 +75,9 @@ static void mainwindow_resize_windows(MAIN_WINDOW_REC *window)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
if (window->resize_freeze_counter > 0) {
|
||||
window->resize_needed = TRUE;
|
||||
return;
|
||||
}
|
||||
if (window->active->width == window->width &&
|
||||
window->active->height == MAIN_WINDOW_TEXT_HEIGHT(window))
|
||||
return;
|
||||
|
||||
mainwindow_set_screen_size(window);
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
|
||||
@ -101,7 +100,7 @@ static void mainwindow_resize(MAIN_WINDOW_REC *window, int xdiff, int ydiff)
|
||||
|
||||
window->width += xdiff;
|
||||
window->height = window->last_line-window->first_line+1;
|
||||
mainwindow_resize_windows(window);
|
||||
window->size_dirty = TRUE;
|
||||
}
|
||||
|
||||
static GSList *get_sticky_windows_sorted(MAIN_WINDOW_REC *mainwin)
|
||||
@ -165,6 +164,7 @@ void mainwindows_recreate(void)
|
||||
MAIN_WINDOW_REC *rec = tmp->data;
|
||||
|
||||
rec->screen_win = mainwindow_create_screen(rec);
|
||||
rec->dirty = TRUE;
|
||||
textbuffer_view_set_window(WINDOW_GUI(rec->active)->view,
|
||||
rec->screen_win);
|
||||
}
|
||||
@ -308,13 +308,12 @@ void mainwindows_redraw(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
term_refresh_freeze();
|
||||
irssi_set_dirty();
|
||||
for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
|
||||
MAIN_WINDOW_REC *rec = tmp->data;
|
||||
|
||||
gui_window_redraw(rec->active);
|
||||
rec->dirty = TRUE;
|
||||
}
|
||||
term_refresh_thaw();
|
||||
}
|
||||
|
||||
static int mainwindows_compare(MAIN_WINDOW_REC *w1, MAIN_WINDOW_REC *w2)
|
||||
@ -453,7 +452,6 @@ void mainwindows_resize(int width, int height)
|
||||
old_screen_width = width;
|
||||
old_screen_height = height;
|
||||
|
||||
term_refresh_freeze();
|
||||
if (ydiff < 0)
|
||||
mainwindows_resize_smaller(xdiff, ydiff);
|
||||
else if (ydiff > 0)
|
||||
@ -462,7 +460,6 @@ void mainwindows_resize(int width, int height)
|
||||
mainwindows_resize_horiz(xdiff);
|
||||
|
||||
signal_emit("terminal resized", 0);
|
||||
term_refresh_thaw();
|
||||
|
||||
irssi_redraw();
|
||||
}
|
||||
@ -521,32 +518,20 @@ int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window,
|
||||
}
|
||||
|
||||
if (top+bottom != 0)
|
||||
mainwindow_resize_windows(window);
|
||||
window->size_dirty = TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mainwindow_resize_freeze(MAIN_WINDOW_REC *window)
|
||||
{
|
||||
window->resize_freeze_counter++;
|
||||
}
|
||||
|
||||
void mainwindow_resize_thaw(MAIN_WINDOW_REC *window)
|
||||
{
|
||||
if (--window->resize_freeze_counter == 0 &&
|
||||
window->resize_needed) {
|
||||
window->resize_needed = FALSE;
|
||||
mainwindow_resize_windows(window);
|
||||
}
|
||||
}
|
||||
|
||||
static void mainwindows_resize_two(MAIN_WINDOW_REC *grow_win,
|
||||
MAIN_WINDOW_REC *shrink_win, int count)
|
||||
{
|
||||
irssi_set_dirty();
|
||||
|
||||
mainwindow_resize(grow_win, 0, count);
|
||||
mainwindow_resize(shrink_win, 0, -count);
|
||||
gui_window_redraw(grow_win->active);
|
||||
gui_window_redraw(shrink_win->active);
|
||||
grow_win->dirty = TRUE;
|
||||
shrink_win->dirty = TRUE;
|
||||
}
|
||||
|
||||
static int try_shrink_lower(MAIN_WINDOW_REC *window, int count)
|
||||
@ -649,6 +634,24 @@ void mainwindow_set_size(MAIN_WINDOW_REC *window, int height, int resize_lower)
|
||||
mainwindow_grow(window, height, resize_lower);
|
||||
}
|
||||
|
||||
void mainwindows_redraw_dirty(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
|
||||
MAIN_WINDOW_REC *rec = tmp->data;
|
||||
|
||||
if (rec->size_dirty) {
|
||||
rec->size_dirty = FALSE;
|
||||
mainwindow_resize_windows(rec);
|
||||
}
|
||||
if (rec->dirty) {
|
||||
rec->dirty = FALSE;
|
||||
gui_window_redraw(rec->active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SYNTAX: WINDOW GROW [<lines>] */
|
||||
static void cmd_window_grow(const char *data)
|
||||
{
|
||||
|
@ -23,8 +23,8 @@ typedef struct {
|
||||
int statusbar_lines_bottom;
|
||||
int statusbar_lines; /* top+bottom */
|
||||
|
||||
int resize_freeze_counter;
|
||||
unsigned int resize_needed:1; /* We'll need to resize the window, but haven't got around doing it just yet. */
|
||||
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;
|
||||
|
||||
extern GSList *mainwindows;
|
||||
@ -53,8 +53,7 @@ void mainwindow_change_active(MAIN_WINDOW_REC *mainwin,
|
||||
int mainwindows_reserve_lines(int top, int bottom);
|
||||
int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window,
|
||||
int top, int bottom);
|
||||
void mainwindow_resize_freeze(MAIN_WINDOW_REC *window);
|
||||
void mainwindow_resize_thaw(MAIN_WINDOW_REC *window);
|
||||
void mainwindows_redraw_dirty(void);
|
||||
|
||||
GSList *mainwindows_get_sorted(int reverse);
|
||||
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
extern int quitting;
|
||||
void irssi_redraw(void);
|
||||
void irssi_set_dirty(void);
|
||||
|
@ -218,7 +218,7 @@ static void create_root_statusbars(void)
|
||||
|
||||
if (rec->type == STATUSBAR_TYPE_ROOT) {
|
||||
bar = statusbar_create(active_statusbar_group, rec, NULL);
|
||||
statusbar_redraw(bar);
|
||||
statusbar_redraw(bar, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,23 +276,23 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
|
||||
{
|
||||
GUI_ENTRY_REC *rec;
|
||||
|
||||
if (get_size_only) {
|
||||
item->min_size = 2+term_width/10;
|
||||
item->max_size = term_width;
|
||||
return;
|
||||
}
|
||||
|
||||
rec = g_hash_table_lookup(input_entries, item);
|
||||
if (rec == NULL) {
|
||||
rec = gui_entry_create(item->xpos, item->bar->real_ypos,
|
||||
item->size);
|
||||
gui_entry_set_active(rec);
|
||||
g_hash_table_insert(input_entries, item, rec);
|
||||
} else {
|
||||
gui_entry_move(rec, item->xpos, item->bar->real_ypos,
|
||||
item->size);
|
||||
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
|
||||
}
|
||||
|
||||
if (get_size_only) {
|
||||
item->min_size = 2+term_width/10;
|
||||
item->max_size = term_width;
|
||||
return;
|
||||
}
|
||||
|
||||
gui_entry_move(rec, item->xpos, item->bar->real_ypos,
|
||||
item->size);
|
||||
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
|
||||
}
|
||||
|
||||
static void sig_statusbar_item_destroyed(SBAR_ITEM_REC *item)
|
||||
|
@ -225,7 +225,12 @@ static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
|
||||
g_slist_free(prior_sorted);
|
||||
}
|
||||
|
||||
static void statusbar_redraw_items(STATUSBAR_REC *bar)
|
||||
#define SBAR_ITEM_REDRAW_NEEDED(_bar, _item, _xpos) \
|
||||
(((_bar)->dirty_xpos != -1 && \
|
||||
(_xpos) >= (_bar)->dirty_xpos) || \
|
||||
(_item)->xpos != (_xpos) || (_item)->current_size != (_item)->size)
|
||||
|
||||
static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
|
||||
{
|
||||
WINDOW_REC *old_active_win;
|
||||
GSList *tmp;
|
||||
@ -237,25 +242,46 @@ static void statusbar_redraw_items(STATUSBAR_REC *bar)
|
||||
|
||||
statusbar_resize_items(bar, term_width);
|
||||
|
||||
/* left-aligned items */
|
||||
xpos = 0;
|
||||
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
|
||||
SBAR_ITEM_REC *rec = tmp->data;
|
||||
|
||||
if (!rec->config->right_alignment && rec->size > 0) {
|
||||
rec->xpos = xpos;
|
||||
xpos += rec->size;
|
||||
rec->func(rec, FALSE);
|
||||
if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
|
||||
/* redraw the item */
|
||||
rec->dirty = TRUE;
|
||||
if (bar->dirty_xpos == -1 ||
|
||||
xpos < bar->dirty_xpos) {
|
||||
irssi_set_dirty();
|
||||
bar->dirty = TRUE;
|
||||
bar->dirty_xpos = xpos;
|
||||
}
|
||||
|
||||
rec->xpos = xpos;
|
||||
}
|
||||
xpos += rec->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* right-aligned items */
|
||||
rxpos = term_width;
|
||||
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
|
||||
SBAR_ITEM_REC *rec = tmp->data;
|
||||
|
||||
if (rec->config->right_alignment && rec->size > 0) {
|
||||
rxpos -= rec->size;
|
||||
rec->xpos = rxpos;
|
||||
rec->func(rec, FALSE);
|
||||
if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
|
||||
rec->dirty = TRUE;
|
||||
if (bar->dirty_xpos == -1 ||
|
||||
xpos < bar->dirty_xpos) {
|
||||
irssi_set_dirty();
|
||||
bar->dirty = TRUE;
|
||||
bar->dirty_xpos = xpos;
|
||||
}
|
||||
rec->xpos = rxpos;
|
||||
}
|
||||
|
||||
rxpos -= rec->size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,26 +302,20 @@ static void statusbar_redraw_items(STATUSBAR_REC *bar)
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
void statusbar_redraw(STATUSBAR_REC *bar)
|
||||
void statusbar_redraw(STATUSBAR_REC *bar, int force)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if (bar == NULL) {
|
||||
if (active_statusbar_group != NULL) {
|
||||
term_refresh_freeze();
|
||||
g_slist_foreach(active_statusbar_group->bars,
|
||||
(GFunc) statusbar_redraw, NULL);
|
||||
term_refresh_thaw();
|
||||
if (bar != NULL) {
|
||||
if (force) {
|
||||
irssi_set_dirty();
|
||||
bar->dirty = TRUE;
|
||||
bar->dirty_xpos = 0;
|
||||
}
|
||||
return;
|
||||
statusbar_calc_item_positions(bar);
|
||||
} else if (active_statusbar_group != NULL) {
|
||||
g_slist_foreach(active_statusbar_group->bars,
|
||||
(GFunc) statusbar_redraw,
|
||||
GINT_TO_POINTER(force));
|
||||
}
|
||||
|
||||
str = g_strconcat(bar->color, "%>", NULL);
|
||||
gui_printtext(0, bar->real_ypos, str);
|
||||
g_free(str);
|
||||
|
||||
statusbar_redraw_items(bar);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
|
||||
void statusbar_item_redraw(SBAR_ITEM_REC *item)
|
||||
@ -309,15 +329,15 @@ void statusbar_item_redraw(SBAR_ITEM_REC *item)
|
||||
active_win = item->bar->parent_window->active;
|
||||
|
||||
item->func(item, TRUE);
|
||||
|
||||
item->dirty = TRUE;
|
||||
item->bar->dirty = TRUE;
|
||||
irssi_set_dirty();
|
||||
|
||||
if (item->max_size != item->size) {
|
||||
/* item wants a new size - we'll need to redraw
|
||||
the statusbar to see if this is allowed */
|
||||
/*FIXME:fprintf(stderr, "%s resizes & redraws whole statusbar", item->config->name);*/
|
||||
statusbar_redraw(item->bar);
|
||||
} else {
|
||||
/*FIXME:fprintf(stderr, "%s redrawing", item->config->name);*/
|
||||
item->func(item, FALSE);
|
||||
term_refresh(NULL);
|
||||
statusbar_redraw(item->bar, FALSE);
|
||||
}
|
||||
|
||||
active_win = old_active_win;
|
||||
@ -374,7 +394,7 @@ static void statusbars_recalc_ypos(STATUSBAR_REC *bar)
|
||||
|
||||
if (bar->real_ypos != ypos) {
|
||||
bar->real_ypos = ypos;
|
||||
statusbar_redraw(bar);
|
||||
statusbar_redraw(bar, TRUE);
|
||||
}
|
||||
|
||||
ypos++;
|
||||
@ -439,6 +459,10 @@ STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group,
|
||||
bar->config = config;
|
||||
bar->parent_window = parent_window;
|
||||
|
||||
irssi_set_dirty();
|
||||
bar->dirty = TRUE;
|
||||
bar->dirty_xpos = 0;
|
||||
|
||||
signal_remove("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
|
||||
signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
|
||||
signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
|
||||
@ -554,7 +578,7 @@ void statusbar_recreate_items(STATUSBAR_REC *bar)
|
||||
statusbar_item_create(bar, rec);
|
||||
}
|
||||
|
||||
statusbar_redraw(bar);
|
||||
statusbar_redraw(bar, TRUE);
|
||||
}
|
||||
|
||||
void statusbars_recreate_items(void)
|
||||
@ -835,6 +859,10 @@ SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar,
|
||||
items = g_slist_append(items, rec);
|
||||
g_hash_table_insert(named_sbar_items, config->name, items);
|
||||
|
||||
irssi_set_dirty();
|
||||
rec->dirty = TRUE;
|
||||
bar->dirty = TRUE;
|
||||
|
||||
signal_emit("statusbar item created", 1, rec);
|
||||
return rec;
|
||||
}
|
||||
@ -893,6 +921,52 @@ void statusbar_item_destroy(SBAR_ITEM_REC *item)
|
||||
g_free(item);
|
||||
}
|
||||
|
||||
static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
|
||||
{
|
||||
WINDOW_REC *old_active_win;
|
||||
GSList *tmp;
|
||||
char *str;
|
||||
|
||||
old_active_win = active_win;
|
||||
if (bar->parent_window != NULL)
|
||||
active_win = bar->parent_window->active;
|
||||
|
||||
if (bar->dirty_xpos >= 0) {
|
||||
str = g_strconcat(bar->color, "%>", NULL);
|
||||
gui_printtext(bar->dirty_xpos, bar->real_ypos, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
|
||||
SBAR_ITEM_REC *rec = tmp->data;
|
||||
|
||||
if (rec->dirty ||
|
||||
(bar->dirty_xpos != -1 &&
|
||||
rec->xpos >= bar->dirty_xpos)) {
|
||||
rec->current_size = rec->size;
|
||||
rec->func(rec, FALSE);
|
||||
rec->dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
active_win = old_active_win;
|
||||
}
|
||||
|
||||
void statusbar_redraw_dirty(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = active_statusbar_group->bars; tmp != NULL; tmp = tmp->next) {
|
||||
STATUSBAR_REC *rec = tmp->data;
|
||||
|
||||
if (rec->dirty) {
|
||||
statusbar_redraw_needed_items(rec);
|
||||
rec->dirty = FALSE;
|
||||
rec->dirty_xpos = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define STATUSBAR_IS_VISIBLE(bar, window) \
|
||||
((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \
|
||||
(active_mainwin == (window) && \
|
||||
@ -927,7 +1001,7 @@ static void statusbars_add_visible(MAIN_WINDOW_REC *window)
|
||||
STATUSBAR_IS_VISIBLE(config, window) &&
|
||||
statusbar_find(group, config->name, window) == NULL) {
|
||||
bar = statusbar_create(group, config, window);
|
||||
statusbar_redraw(bar);
|
||||
statusbar_redraw(bar, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -951,10 +1025,8 @@ static void sig_window_changed(void)
|
||||
for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
|
||||
MAIN_WINDOW_REC *rec = tmp->data;
|
||||
|
||||
mainwindow_resize_freeze(rec);
|
||||
statusbars_remove_unvisible(rec);
|
||||
statusbars_add_visible(rec);
|
||||
mainwindow_resize_thaw(rec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,9 @@ typedef struct {
|
||||
|
||||
char *color; /* background color */
|
||||
int real_ypos; /* real Y-position in screen at the moment */
|
||||
|
||||
int dirty:1;
|
||||
int dirty_xpos; /* -1 = only redraw some items, >= 0 = redraw all items after from xpos */
|
||||
} STATUSBAR_REC;
|
||||
|
||||
typedef struct {
|
||||
@ -69,6 +72,9 @@ struct SBAR_ITEM_REC {
|
||||
|
||||
/* what item gets */
|
||||
int xpos, size;
|
||||
|
||||
int current_size; /* item size currently in screen */
|
||||
int dirty:1;
|
||||
};
|
||||
|
||||
extern GSList *statusbar_groups;
|
||||
@ -98,13 +104,15 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
|
||||
int escape_vars);
|
||||
|
||||
/* redraw statusbar, NULL = all */
|
||||
void statusbar_redraw(STATUSBAR_REC *bar);
|
||||
void statusbar_redraw(STATUSBAR_REC *bar, int force);
|
||||
void statusbar_item_redraw(SBAR_ITEM_REC *item);
|
||||
void statusbar_items_redraw(const char *name);
|
||||
|
||||
void statusbar_recreate_items(STATUSBAR_REC *bar);
|
||||
void statusbars_recreate_items(void);
|
||||
|
||||
void statusbar_redraw_dirty(void);
|
||||
|
||||
void statusbar_init(void);
|
||||
void statusbar_deinit(void);
|
||||
|
||||
|
@ -37,6 +37,7 @@ struct _TERM_WINDOW {
|
||||
TERM_WINDOW *root_window;
|
||||
int term_width, term_height;
|
||||
|
||||
static int vcx, vcy;
|
||||
static int curs_x, curs_y;
|
||||
static int last_fg, last_bg, last_attrs;
|
||||
static int redraw_needed, redraw_tag;
|
||||
@ -63,7 +64,8 @@ int term_init(void)
|
||||
struct sigaction act;
|
||||
|
||||
last_fg = last_bg = -1;
|
||||
last_attrs = 0;
|
||||
last_attrs = 0;
|
||||
vcx = vcy = -1;
|
||||
|
||||
current_term = terminfo_core_init(stdin, stdout);
|
||||
if (current_term == NULL)
|
||||
@ -108,6 +110,8 @@ void term_resize(int width, int height)
|
||||
term_height = current_term->height = height;
|
||||
term_window_move(root_window, 0, 0, term_width, term_height);
|
||||
}
|
||||
|
||||
vcx = vcy = -1;
|
||||
}
|
||||
|
||||
/* Returns TRUE if terminal has colors */
|
||||
@ -125,13 +129,14 @@ void term_force_colors(int set)
|
||||
/* Clear screen */
|
||||
void term_clear(void)
|
||||
{
|
||||
vcx = vcy = -1;
|
||||
terminfo_clear();
|
||||
}
|
||||
|
||||
/* Beep */
|
||||
void term_beep(void)
|
||||
{
|
||||
/* FIXME */
|
||||
terminfo_beep(current_term);
|
||||
}
|
||||
|
||||
/* Create a new window in terminal */
|
||||
@ -169,14 +174,15 @@ void term_window_clear(TERM_WINDOW *window)
|
||||
|
||||
terminfo_set_normal();
|
||||
for (y = 0; y < window->height; y++) {
|
||||
terminfo_move(0, window->y+y);
|
||||
terminfo_clrtoeol();
|
||||
term_move(window, 0, y);
|
||||
term_clrtoeol(window);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll window up/down */
|
||||
void term_window_scroll(TERM_WINDOW *window, int count)
|
||||
{
|
||||
vcx = vcy = -1;
|
||||
terminfo_scroll(window->y, window->y+window->height-1, count);
|
||||
}
|
||||
|
||||
@ -244,17 +250,32 @@ void term_set_color(TERM_WINDOW *window, int col)
|
||||
|
||||
void term_move(TERM_WINDOW *window, int x, int y)
|
||||
{
|
||||
terminfo_move(x+window->x, y+window->y);
|
||||
int newx, newy;
|
||||
|
||||
newx = x+window->x;
|
||||
newy = y+window->y;
|
||||
if (vcx != newx || vcy != newy) {
|
||||
terminfo_move_relative(vcx, vcy, newx, newy);
|
||||
vcx = newx; vcy = newy;
|
||||
}
|
||||
}
|
||||
|
||||
void term_addch(TERM_WINDOW *window, int chr)
|
||||
{
|
||||
putc(chr, window->term->out);
|
||||
putc(chr, window->term->out);
|
||||
if (++vcx == window->width) {
|
||||
vcx = 0; vcy++;
|
||||
}
|
||||
}
|
||||
|
||||
void term_addstr(TERM_WINDOW *window, char *str)
|
||||
{
|
||||
fputs(str, window->term->out);
|
||||
fputs(str, window->term->out);
|
||||
vcx += strlen(str);
|
||||
while (vcx > window->width) {
|
||||
vcx -= window->width;
|
||||
vcy++;
|
||||
}
|
||||
}
|
||||
|
||||
void term_clrtoeol(TERM_WINDOW *window)
|
||||
@ -270,7 +291,8 @@ void term_move_cursor(int x, int y)
|
||||
|
||||
void term_refresh(TERM_WINDOW *window)
|
||||
{
|
||||
terminfo_move(curs_x, curs_y);
|
||||
if (vcx != curs_x || vcy != curs_y)
|
||||
term_move(root_window, curs_x, curs_y);
|
||||
fflush(window != NULL ? window->term->out : current_term->out);
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ static TERMINFO_REC tcaps[] = {
|
||||
{ "cup", "cm", CAP_TYPE_STR, &temp_term.TI_cup },
|
||||
{ "hpa", "ch", CAP_TYPE_STR, &temp_term.TI_hpa },
|
||||
{ "vpa", "vh", CAP_TYPE_STR, &temp_term.TI_vpa },
|
||||
{ "xvpa", "YD", CAP_TYPE_FLAG, &temp_term.TI_xvpa },
|
||||
{ "hvpa", "YA", CAP_TYPE_FLAG, &temp_term.TI_xhpa },
|
||||
{ "cub1", "le", CAP_TYPE_STR, &temp_term.TI_cub1 },
|
||||
{ "cuf1", "nd", CAP_TYPE_STR, &temp_term.TI_cuf1 },
|
||||
|
||||
/* Scrolling */
|
||||
{ "csr", "cs", CAP_TYPE_STR, &temp_term.TI_csr },
|
||||
@ -113,6 +113,40 @@ static void _move_pa(TERM_REC *term, int x, int y)
|
||||
tput(tparm(term->TI_vpa, y));
|
||||
}
|
||||
|
||||
/* Move cursor from a known position */
|
||||
static void _move_relative(TERM_REC *term, int oldx, int oldy, int x, int y)
|
||||
{
|
||||
if (oldx == 0 && x == 0 && y == oldy+1) {
|
||||
/* move to beginning of next line -
|
||||
hope this works everywhere */
|
||||
tput("\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldx > 0 && y == oldy) {
|
||||
/* move cursor left/right */
|
||||
if (x == oldx-1 && term->TI_cub1) {
|
||||
tput(tparm(term->TI_cub1));
|
||||
return;
|
||||
}
|
||||
if (x == oldx+1 && y == oldy && term->TI_cuf1) {
|
||||
tput(tparm(term->TI_cuf1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* fallback to absolute positioning */
|
||||
if (term->TI_cup) {
|
||||
tput(tparm(term->TI_cup, y, x));
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldy != y)
|
||||
tput(tparm(term->TI_vpa, y));
|
||||
if (oldx != x)
|
||||
tput(tparm(term->TI_hpa, x));
|
||||
}
|
||||
|
||||
#define scroll_region_setup(term, y1, y2) \
|
||||
if ((term)->TI_csr != NULL) \
|
||||
tput(tparm((term)->TI_csr, y1, y2)); \
|
||||
@ -474,14 +508,15 @@ static int term_setup(TERM_REC *term)
|
||||
/* Cursor movement */
|
||||
if (term->TI_cup)
|
||||
term->move = _move_cup;
|
||||
else if (term->TI_hpa && term->TI_vpa &&
|
||||
!term->TI_xhpa && !term->TI_xvpa)
|
||||
else if (term->TI_hpa && term->TI_vpa)
|
||||
term->move = _move_pa;
|
||||
else {
|
||||
fprintf(term->out, "Terminal doesn't support cursor movement\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
term->move_relative = _move_relative;
|
||||
|
||||
/* Scrolling */
|
||||
if ((term->TI_csr || term->TI_wind) && term->TI_rin && term->TI_indn)
|
||||
term->scroll = _scroll_region;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <termios.h>
|
||||
|
||||
#define terminfo_move(x, y) current_term->move(current_term, x, y)
|
||||
#define terminfo_move_relative(oldx, oldy, x, y) current_term->move_relative(current_term, oldx, oldy, x, y)
|
||||
#define terminfo_scroll(y1, y2, count) current_term->scroll(current_term, y1, y2, count)
|
||||
#define terminfo_clear() current_term->clear(current_term)
|
||||
#define terminfo_clrtoeol() current_term->clrtoeol(current_term)
|
||||
@ -14,12 +15,14 @@
|
||||
#define terminfo_set_uline(set) current_term->set_uline(current_term, set)
|
||||
#define terminfo_set_standout(set) current_term->set_standout(current_term, set)
|
||||
#define terminfo_has_colors(term) (term->TI_fg[0] != NULL)
|
||||
#define terminfo_beep(term) current_term->beep(current_term)
|
||||
|
||||
typedef struct _TERM_REC TERM_REC;
|
||||
|
||||
struct _TERM_REC {
|
||||
/* Functions */
|
||||
void (*move)(TERM_REC *term, int x, int y);
|
||||
void (*move_relative)(TERM_REC *term, int oldx, int oldy, int x, int y);
|
||||
void (*scroll)(TERM_REC *term, int y1, int y2, int count);
|
||||
|
||||
void (*clear)(TERM_REC *term);
|
||||
@ -45,8 +48,7 @@ struct _TERM_REC {
|
||||
|
||||
/* Cursor movement */
|
||||
const char *TI_smcup, *TI_rmcup, *TI_cup;
|
||||
const char *TI_hpa, *TI_vpa;
|
||||
int TI_xhpa, TI_xvpa;
|
||||
const char *TI_hpa, *TI_vpa, *TI_cub1, *TI_cuf1;
|
||||
|
||||
/* Scrolling */
|
||||
const char *TI_csr, *TI_wind;
|
||||
|
@ -307,6 +307,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
char *tmp;
|
||||
int xpos, color, drawcount, first;
|
||||
|
||||
if (view->dirty) /* don't bother drawing anything - redraw is coming */
|
||||
return 0;
|
||||
|
||||
cache = textbuffer_view_get_line_cache(view, line);
|
||||
if (subline >= cache->count)
|
||||
return 0;
|
||||
@ -581,10 +584,13 @@ static int view_get_linecount_all(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
}
|
||||
|
||||
static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
int subline, int ypos, int lines)
|
||||
int subline, int ypos, int lines, int fill_bottom)
|
||||
{
|
||||
int linecount;
|
||||
|
||||
if (view->dirty) /* don't bother drawing anything - redraw is coming */
|
||||
return;
|
||||
|
||||
while (line != NULL && lines > 0) {
|
||||
linecount = view_line_draw(view, line, subline, ypos, lines);
|
||||
ypos += linecount; lines -= linecount;
|
||||
@ -593,17 +599,20 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
/* clear the rest of the view */
|
||||
term_set_color(view->window, ATTR_RESET);
|
||||
while (lines > 0) {
|
||||
term_move(view->window, 0, ypos);
|
||||
term_clrtoeol(view->window);
|
||||
ypos++; lines--;
|
||||
if (fill_bottom) {
|
||||
/* clear the rest of the view */
|
||||
term_set_color(view->window, ATTR_RESET);
|
||||
while (lines > 0) {
|
||||
term_move(view->window, 0, ypos);
|
||||
term_clrtoeol(view->window);
|
||||
ypos++; lines--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define view_draw_top(view, lines) \
|
||||
view_draw(view, (view)->startline, (view)->subline, 0, lines)
|
||||
#define view_draw_top(view, lines, fill_bottom) \
|
||||
view_draw(view, (view)->startline, (view)->subline, \
|
||||
0, lines, fill_bottom)
|
||||
|
||||
static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines)
|
||||
{
|
||||
@ -622,7 +631,7 @@ static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines)
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
view_draw(view, line, subline, maxline, lines);
|
||||
view_draw(view, line, subline, maxline, lines, TRUE);
|
||||
}
|
||||
|
||||
/* Returns number of lines actually scrolled */
|
||||
@ -687,7 +696,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
|
||||
|
||||
if (draw_nonclean) {
|
||||
if (realcount < 0)
|
||||
view_draw_top(view, -realcount);
|
||||
view_draw_top(view, -realcount, TRUE);
|
||||
else
|
||||
view_draw_bottom(view, realcount);
|
||||
}
|
||||
@ -760,7 +769,7 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
|
||||
view->empty_linecount = view->height-linecount;
|
||||
}
|
||||
|
||||
textbuffer_view_redraw(view);
|
||||
view->dirty = TRUE;
|
||||
}
|
||||
|
||||
/* Clear the view, don't actually remove any lines from buffer. */
|
||||
@ -1154,8 +1163,8 @@ void textbuffer_view_set_window(TEXT_BUFFER_VIEW_REC *view,
|
||||
|
||||
if (view->window != window) {
|
||||
view->window = window;
|
||||
if (window != NULL)
|
||||
textbuffer_view_redraw(view);
|
||||
if (window != NULL)
|
||||
view->dirty = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1165,8 +1174,9 @@ void textbuffer_view_redraw(TEXT_BUFFER_VIEW_REC *view)
|
||||
g_return_if_fail(view != NULL);
|
||||
|
||||
if (view->window != NULL) {
|
||||
view->dirty = FALSE;
|
||||
term_window_clear(view->window);
|
||||
view_draw_top(view, view->height);
|
||||
view_draw_top(view, view->height, FALSE);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,8 @@ struct _TEXT_BUFFER_VIEW_REC {
|
||||
int empty_linecount;
|
||||
/* window is at the bottom of the text buffer */
|
||||
unsigned int bottom:1;
|
||||
/* Window needs a redraw */
|
||||
unsigned int dirty:1;
|
||||
|
||||
/* Bookmarks to the lines in the buffer - removed automatically
|
||||
when the line gets removed from buffer */
|
||||
|
Loading…
Reference in New Issue
Block a user