1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05: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:
Timo Sirainen 2001-10-28 18:40:12 +00:00 committed by cras
parent 44b12481d6
commit fb439b5c2a
16 changed files with 348 additions and 123 deletions

View File

@ -54,6 +54,9 @@ void gui_entry_destroy(GUI_ENTRY_REC *entry)
/* Fixes the cursor position in screen */ /* Fixes the cursor position in screen */
static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry) 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 && if (entry->pos - entry->scrstart < entry->width-2 - entry->promptlen &&
entry->pos - entry->scrstart > 0) { entry->pos - entry->scrstart > 0) {
entry->scrpos = entry->pos - entry->scrstart; 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->scrpos = (entry->width - entry->promptlen)*2/3;
entry->scrstart = entry->pos - entry->scrpos; 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) 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++; 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, term_move_cursor(entry->xpos + entry->scrpos + entry->promptlen,
entry->ypos); entry->ypos);
term_refresh(NULL); 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) 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 */ /* input line grew - need to draw text at the end */
old_width = width; old_width = width;
entry->width = width; entry->width = width;
gui_entry_draw_from(entry, old_width); gui_entry_redraw_from(entry, old_width);
} else { } else {
/* input line shrinked - make sure the cursor /* input line shrinked - make sure the cursor
is inside the input line */ 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 > if (entry->pos - entry->scrstart >
entry->width-2 - entry->promptlen) { entry->width-2 - entry->promptlen) {
gui_entry_fix_cursor(entry); gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
} }
} }
gui_entry_draw(entry);
} }
void gui_entry_set_active(GUI_ENTRY_REC *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); g_string_assign(entry->text, str);
entry->pos = entry->text->len; entry->pos = entry->text->len;
gui_entry_redraw_from(entry, 0);
gui_entry_fix_cursor(entry); gui_entry_fix_cursor(entry);
gui_entry_draw(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(entry != NULL);
g_return_if_fail(str != NULL); g_return_if_fail(str != NULL);
gui_entry_redraw_from(entry, entry->pos);
g_string_insert(entry->text, entry->pos, str); g_string_insert(entry->text, entry->pos, str);
entry->pos += strlen(str); entry->pos += strlen(str);
@ -226,6 +248,7 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
if (chr == 0) if (chr == 0)
return; /* never insert NUL characters */ return; /* never insert NUL characters */
gui_entry_redraw_from(entry, entry->pos);
g_string_insert_c(entry->text, entry->pos, chr); g_string_insert_c(entry->text, entry->pos, chr);
entry->pos++; entry->pos++;
@ -249,6 +272,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
entry->pos -= size; entry->pos -= size;
g_string_erase(entry->text, 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_fix_cursor(entry);
gui_entry_draw(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); g_string_erase(entry->text, to, entry->pos - to);
entry->pos = to; entry->pos = to;
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry); gui_entry_fix_cursor(entry);
gui_entry_draw(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); g_string_erase(entry->text, entry->pos, to - entry->pos);
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry); gui_entry_fix_cursor(entry);
gui_entry_draw(entry); gui_entry_draw(entry);
} }
@ -412,6 +438,7 @@ void gui_entry_redraw(GUI_ENTRY_REC *entry)
g_return_if_fail(entry != NULL); g_return_if_fail(entry != NULL);
gui_entry_set_prompt(entry, NULL); gui_entry_set_prompt(entry, NULL);
gui_entry_redraw_from(entry, 0);
gui_entry_fix_cursor(entry); gui_entry_fix_cursor(entry);
gui_entry_draw(entry); gui_entry_draw(entry);
} }

View File

@ -8,7 +8,9 @@ typedef struct {
int hidden; /* print the chars as spaces in input line (useful for passwords) */ int hidden; /* print the chars as spaces in input line (useful for passwords) */
int promptlen; int promptlen;
char *prompt; char *prompt;
int redraw_needed_from;
} GUI_ENTRY_REC; } GUI_ENTRY_REC;
extern GUI_ENTRY_REC *active_entry; extern GUI_ENTRY_REC *active_entry;

View File

@ -117,8 +117,14 @@ void gui_window_resize(WINDOW_REC *window, int width, int height)
{ {
GUI_WINDOW_REC *gui; GUI_WINDOW_REC *gui;
if (window->width == width && window->height == height)
return;
gui = WINDOW_GUI(window); gui = WINDOW_GUI(window);
irssi_set_dirty();
WINDOW_MAIN(window)->dirty = TRUE;
window->width = width; window->width = width;
window->height = height; window->height = height;
textbuffer_view_resize(gui->view, width, 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); gui_window_reparent(window, active_mainwin);
} }
old_window = active_mainwin->active; old_window = active_mainwin->active;
if (old_window != NULL) if (old_window != NULL && old_window != window)
textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL); textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL);
active_mainwin->active = window; active_mainwin->active = window;
textbuffer_view_set_window(WINDOW_GUI(window)->view, textbuffer_view_set_window(WINDOW_GUI(window)->view,
parent->screen_win); parent->screen_win);
if (WINDOW_GUI(window)->view->dirty)
active_mainwin->dirty = TRUE;
} }
static void read_settings(void) static void read_settings(void)

View File

@ -69,6 +69,8 @@ void mainwindow_activity_deinit(void);
void mainwindows_layout_init(void); void mainwindows_layout_init(void);
void mainwindows_layout_deinit(void); void mainwindows_layout_deinit(void);
static int dirty, full_redraw;
static GMainLoop *main_loop; static GMainLoop *main_loop;
int quitting; int quitting;
@ -85,19 +87,43 @@ static int display_firsttimer = FALSE;
static void sig_exit(void) static void sig_exit(void)
{ {
g_main_quit(main_loop); quitting = TRUE;
} }
/* redraw irssi's screen.. */ /* redraw irssi's screen.. */
void irssi_redraw(void) 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); term_refresh(NULL);
/* windows */ dirty = FALSE;
mainwindows_redraw();
/* statusbar */
statusbar_redraw(NULL);
} }
static void textui_init(void) static void textui_init(void)
@ -152,7 +178,6 @@ static void textui_finish_init(void)
static void textui_deinit(void) static void textui_deinit(void)
{ {
quitting = TRUE;
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
term_refresh_freeze(); term_refresh_freeze();
@ -164,6 +189,7 @@ static void textui_deinit(void)
fe_perl_deinit(); fe_perl_deinit();
#endif #endif
dirty_check(); /* one last time to print any quit messages */
signal_remove("gui exit", (SIGNAL_FUNC) sig_exit); signal_remove("gui exit", (SIGNAL_FUNC) sig_exit);
lastlog_deinit(); lastlog_deinit();
@ -256,6 +282,7 @@ static void winsock_init(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
quitting = FALSE;
core_init_paths(argc, argv); core_init_paths(argc, argv);
check_files(); check_files();
@ -279,7 +306,14 @@ int main(int argc, char **argv)
textui_finish_init(); textui_finish_init();
main_loop = g_main_new(TRUE); 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); g_main_destroy(main_loop);
textui_deinit(); textui_deinit();

View File

@ -75,10 +75,9 @@ static void mainwindow_resize_windows(MAIN_WINDOW_REC *window)
{ {
GSList *tmp; GSList *tmp;
if (window->resize_freeze_counter > 0) { if (window->active->width == window->width &&
window->resize_needed = TRUE; window->active->height == MAIN_WINDOW_TEXT_HEIGHT(window))
return; return;
}
mainwindow_set_screen_size(window); mainwindow_set_screen_size(window);
for (tmp = windows; tmp != NULL; tmp = tmp->next) { 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->width += xdiff;
window->height = window->last_line-window->first_line+1; 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) static GSList *get_sticky_windows_sorted(MAIN_WINDOW_REC *mainwin)
@ -165,6 +164,7 @@ void mainwindows_recreate(void)
MAIN_WINDOW_REC *rec = tmp->data; MAIN_WINDOW_REC *rec = tmp->data;
rec->screen_win = mainwindow_create_screen(rec); rec->screen_win = mainwindow_create_screen(rec);
rec->dirty = TRUE;
textbuffer_view_set_window(WINDOW_GUI(rec->active)->view, textbuffer_view_set_window(WINDOW_GUI(rec->active)->view,
rec->screen_win); rec->screen_win);
} }
@ -308,13 +308,12 @@ void mainwindows_redraw(void)
{ {
GSList *tmp; GSList *tmp;
term_refresh_freeze(); irssi_set_dirty();
for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
MAIN_WINDOW_REC *rec = tmp->data; 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) 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_width = width;
old_screen_height = height; old_screen_height = height;
term_refresh_freeze();
if (ydiff < 0) if (ydiff < 0)
mainwindows_resize_smaller(xdiff, ydiff); mainwindows_resize_smaller(xdiff, ydiff);
else if (ydiff > 0) else if (ydiff > 0)
@ -462,7 +460,6 @@ void mainwindows_resize(int width, int height)
mainwindows_resize_horiz(xdiff); mainwindows_resize_horiz(xdiff);
signal_emit("terminal resized", 0); signal_emit("terminal resized", 0);
term_refresh_thaw();
irssi_redraw(); irssi_redraw();
} }
@ -521,32 +518,20 @@ int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window,
} }
if (top+bottom != 0) if (top+bottom != 0)
mainwindow_resize_windows(window); window->size_dirty = TRUE;
return ret; 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, static void mainwindows_resize_two(MAIN_WINDOW_REC *grow_win,
MAIN_WINDOW_REC *shrink_win, int count) MAIN_WINDOW_REC *shrink_win, int count)
{ {
irssi_set_dirty();
mainwindow_resize(grow_win, 0, count); mainwindow_resize(grow_win, 0, count);
mainwindow_resize(shrink_win, 0, -count); mainwindow_resize(shrink_win, 0, -count);
gui_window_redraw(grow_win->active); grow_win->dirty = TRUE;
gui_window_redraw(shrink_win->active); shrink_win->dirty = TRUE;
} }
static int try_shrink_lower(MAIN_WINDOW_REC *window, int count) 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); 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>] */ /* SYNTAX: WINDOW GROW [<lines>] */
static void cmd_window_grow(const char *data) static void cmd_window_grow(const char *data)
{ {

View File

@ -23,8 +23,8 @@ typedef struct {
int statusbar_lines_bottom; int statusbar_lines_bottom;
int statusbar_lines; /* top+bottom */ int statusbar_lines; /* top+bottom */
int resize_freeze_counter; unsigned int dirty:1; /* This window needs a redraw */
unsigned int resize_needed: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;
extern GSList *mainwindows; extern GSList *mainwindows;
@ -53,8 +53,7 @@ void mainwindow_change_active(MAIN_WINDOW_REC *mainwin,
int mainwindows_reserve_lines(int top, int bottom); int mainwindows_reserve_lines(int top, int bottom);
int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window, int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window,
int top, int bottom); int top, int bottom);
void mainwindow_resize_freeze(MAIN_WINDOW_REC *window); void mainwindows_redraw_dirty(void);
void mainwindow_resize_thaw(MAIN_WINDOW_REC *window);
GSList *mainwindows_get_sorted(int reverse); GSList *mainwindows_get_sorted(int reverse);

View File

@ -4,3 +4,4 @@
extern int quitting; extern int quitting;
void irssi_redraw(void); void irssi_redraw(void);
void irssi_set_dirty(void);

View File

@ -218,7 +218,7 @@ static void create_root_statusbars(void)
if (rec->type == STATUSBAR_TYPE_ROOT) { if (rec->type == STATUSBAR_TYPE_ROOT) {
bar = statusbar_create(active_statusbar_group, rec, NULL); bar = statusbar_create(active_statusbar_group, rec, NULL);
statusbar_redraw(bar); statusbar_redraw(bar, TRUE);
} }
} }
} }

View File

@ -276,23 +276,23 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
{ {
GUI_ENTRY_REC *rec; 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); rec = g_hash_table_lookup(input_entries, item);
if (rec == NULL) { if (rec == NULL) {
rec = gui_entry_create(item->xpos, item->bar->real_ypos, rec = gui_entry_create(item->xpos, item->bar->real_ypos,
item->size); item->size);
gui_entry_set_active(rec); gui_entry_set_active(rec);
g_hash_table_insert(input_entries, item, 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) static void sig_statusbar_item_destroyed(SBAR_ITEM_REC *item)

View File

@ -225,7 +225,12 @@ static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
g_slist_free(prior_sorted); 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; WINDOW_REC *old_active_win;
GSList *tmp; GSList *tmp;
@ -237,25 +242,46 @@ static void statusbar_redraw_items(STATUSBAR_REC *bar)
statusbar_resize_items(bar, term_width); statusbar_resize_items(bar, term_width);
/* left-aligned items */
xpos = 0; xpos = 0;
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data; SBAR_ITEM_REC *rec = tmp->data;
if (!rec->config->right_alignment && rec->size > 0) { if (!rec->config->right_alignment && rec->size > 0) {
rec->xpos = xpos; if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
xpos += rec->size; /* redraw the item */
rec->func(rec, FALSE); 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; rxpos = term_width;
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
SBAR_ITEM_REC *rec = tmp->data; SBAR_ITEM_REC *rec = tmp->data;
if (rec->config->right_alignment && rec->size > 0) { if (rec->config->right_alignment && rec->size > 0) {
rxpos -= rec->size; if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
rec->xpos = rxpos; rec->dirty = TRUE;
rec->func(rec, FALSE); 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; return NULL;
}*/ }*/
void statusbar_redraw(STATUSBAR_REC *bar) void statusbar_redraw(STATUSBAR_REC *bar, int force)
{ {
char *str; if (bar != NULL) {
if (force) {
if (bar == NULL) { irssi_set_dirty();
if (active_statusbar_group != NULL) { bar->dirty = TRUE;
term_refresh_freeze(); bar->dirty_xpos = 0;
g_slist_foreach(active_statusbar_group->bars,
(GFunc) statusbar_redraw, NULL);
term_refresh_thaw();
} }
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) 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; active_win = item->bar->parent_window->active;
item->func(item, TRUE); item->func(item, TRUE);
item->dirty = TRUE;
item->bar->dirty = TRUE;
irssi_set_dirty();
if (item->max_size != item->size) { if (item->max_size != item->size) {
/* item wants a new size - we'll need to redraw /* item wants a new size - we'll need to redraw
the statusbar to see if this is allowed */ the statusbar to see if this is allowed */
/*FIXME:fprintf(stderr, "%s resizes & redraws whole statusbar", item->config->name);*/ statusbar_redraw(item->bar, FALSE);
statusbar_redraw(item->bar);
} else {
/*FIXME:fprintf(stderr, "%s redrawing", item->config->name);*/
item->func(item, FALSE);
term_refresh(NULL);
} }
active_win = old_active_win; active_win = old_active_win;
@ -374,7 +394,7 @@ static void statusbars_recalc_ypos(STATUSBAR_REC *bar)
if (bar->real_ypos != ypos) { if (bar->real_ypos != ypos) {
bar->real_ypos = ypos; bar->real_ypos = ypos;
statusbar_redraw(bar); statusbar_redraw(bar, TRUE);
} }
ypos++; ypos++;
@ -439,6 +459,10 @@ STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group,
bar->config = config; bar->config = config;
bar->parent_window = parent_window; 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("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized); signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
signal_remove("mainwindow moved", (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_item_create(bar, rec);
} }
statusbar_redraw(bar); statusbar_redraw(bar, TRUE);
} }
void statusbars_recreate_items(void) void statusbars_recreate_items(void)
@ -835,6 +859,10 @@ SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar,
items = g_slist_append(items, rec); items = g_slist_append(items, rec);
g_hash_table_insert(named_sbar_items, config->name, items); 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); signal_emit("statusbar item created", 1, rec);
return rec; return rec;
} }
@ -893,6 +921,52 @@ void statusbar_item_destroy(SBAR_ITEM_REC *item)
g_free(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) \ #define STATUSBAR_IS_VISIBLE(bar, window) \
((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \ ((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \
(active_mainwin == (window) && \ (active_mainwin == (window) && \
@ -927,7 +1001,7 @@ static void statusbars_add_visible(MAIN_WINDOW_REC *window)
STATUSBAR_IS_VISIBLE(config, window) && STATUSBAR_IS_VISIBLE(config, window) &&
statusbar_find(group, config->name, window) == NULL) { statusbar_find(group, config->name, window) == NULL) {
bar = statusbar_create(group, config, window); 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) { for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
MAIN_WINDOW_REC *rec = tmp->data; MAIN_WINDOW_REC *rec = tmp->data;
mainwindow_resize_freeze(rec);
statusbars_remove_unvisible(rec); statusbars_remove_unvisible(rec);
statusbars_add_visible(rec); statusbars_add_visible(rec);
mainwindow_resize_thaw(rec);
} }
} }

View File

@ -49,6 +49,9 @@ typedef struct {
char *color; /* background color */ char *color; /* background color */
int real_ypos; /* real Y-position in screen at the moment */ 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; } STATUSBAR_REC;
typedef struct { typedef struct {
@ -69,6 +72,9 @@ struct SBAR_ITEM_REC {
/* what item gets */ /* what item gets */
int xpos, size; int xpos, size;
int current_size; /* item size currently in screen */
int dirty:1;
}; };
extern GSList *statusbar_groups; extern GSList *statusbar_groups;
@ -98,13 +104,15 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
int escape_vars); int escape_vars);
/* redraw statusbar, NULL = all */ /* 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_item_redraw(SBAR_ITEM_REC *item);
void statusbar_items_redraw(const char *name); void statusbar_items_redraw(const char *name);
void statusbar_recreate_items(STATUSBAR_REC *bar); void statusbar_recreate_items(STATUSBAR_REC *bar);
void statusbars_recreate_items(void); void statusbars_recreate_items(void);
void statusbar_redraw_dirty(void);
void statusbar_init(void); void statusbar_init(void);
void statusbar_deinit(void); void statusbar_deinit(void);

View File

@ -37,6 +37,7 @@ struct _TERM_WINDOW {
TERM_WINDOW *root_window; TERM_WINDOW *root_window;
int term_width, term_height; int term_width, term_height;
static int vcx, vcy;
static int curs_x, curs_y; static int curs_x, curs_y;
static int last_fg, last_bg, last_attrs; static int last_fg, last_bg, last_attrs;
static int redraw_needed, redraw_tag; static int redraw_needed, redraw_tag;
@ -63,7 +64,8 @@ int term_init(void)
struct sigaction act; struct sigaction act;
last_fg = last_bg = -1; last_fg = last_bg = -1;
last_attrs = 0; last_attrs = 0;
vcx = vcy = -1;
current_term = terminfo_core_init(stdin, stdout); current_term = terminfo_core_init(stdin, stdout);
if (current_term == NULL) if (current_term == NULL)
@ -108,6 +110,8 @@ void term_resize(int width, int height)
term_height = current_term->height = height; term_height = current_term->height = height;
term_window_move(root_window, 0, 0, term_width, term_height); term_window_move(root_window, 0, 0, term_width, term_height);
} }
vcx = vcy = -1;
} }
/* Returns TRUE if terminal has colors */ /* Returns TRUE if terminal has colors */
@ -125,13 +129,14 @@ void term_force_colors(int set)
/* Clear screen */ /* Clear screen */
void term_clear(void) void term_clear(void)
{ {
vcx = vcy = -1;
terminfo_clear(); terminfo_clear();
} }
/* Beep */ /* Beep */
void term_beep(void) void term_beep(void)
{ {
/* FIXME */ terminfo_beep(current_term);
} }
/* Create a new window in terminal */ /* Create a new window in terminal */
@ -169,14 +174,15 @@ void term_window_clear(TERM_WINDOW *window)
terminfo_set_normal(); terminfo_set_normal();
for (y = 0; y < window->height; y++) { for (y = 0; y < window->height; y++) {
terminfo_move(0, window->y+y); term_move(window, 0, y);
terminfo_clrtoeol(); term_clrtoeol(window);
} }
} }
/* Scroll window up/down */ /* Scroll window up/down */
void term_window_scroll(TERM_WINDOW *window, int count) void term_window_scroll(TERM_WINDOW *window, int count)
{ {
vcx = vcy = -1;
terminfo_scroll(window->y, window->y+window->height-1, count); 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) 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) 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) 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) void term_clrtoeol(TERM_WINDOW *window)
@ -270,7 +291,8 @@ void term_move_cursor(int x, int y)
void term_refresh(TERM_WINDOW *window) 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); fflush(window != NULL ? window->term->out : current_term->out);
} }

View File

@ -61,8 +61,8 @@ static TERMINFO_REC tcaps[] = {
{ "cup", "cm", CAP_TYPE_STR, &temp_term.TI_cup }, { "cup", "cm", CAP_TYPE_STR, &temp_term.TI_cup },
{ "hpa", "ch", CAP_TYPE_STR, &temp_term.TI_hpa }, { "hpa", "ch", CAP_TYPE_STR, &temp_term.TI_hpa },
{ "vpa", "vh", CAP_TYPE_STR, &temp_term.TI_vpa }, { "vpa", "vh", CAP_TYPE_STR, &temp_term.TI_vpa },
{ "xvpa", "YD", CAP_TYPE_FLAG, &temp_term.TI_xvpa }, { "cub1", "le", CAP_TYPE_STR, &temp_term.TI_cub1 },
{ "hvpa", "YA", CAP_TYPE_FLAG, &temp_term.TI_xhpa }, { "cuf1", "nd", CAP_TYPE_STR, &temp_term.TI_cuf1 },
/* Scrolling */ /* Scrolling */
{ "csr", "cs", CAP_TYPE_STR, &temp_term.TI_csr }, { "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)); 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) \ #define scroll_region_setup(term, y1, y2) \
if ((term)->TI_csr != NULL) \ if ((term)->TI_csr != NULL) \
tput(tparm((term)->TI_csr, y1, y2)); \ tput(tparm((term)->TI_csr, y1, y2)); \
@ -474,14 +508,15 @@ static int term_setup(TERM_REC *term)
/* Cursor movement */ /* Cursor movement */
if (term->TI_cup) if (term->TI_cup)
term->move = _move_cup; term->move = _move_cup;
else if (term->TI_hpa && term->TI_vpa && else if (term->TI_hpa && term->TI_vpa)
!term->TI_xhpa && !term->TI_xvpa)
term->move = _move_pa; term->move = _move_pa;
else { else {
fprintf(term->out, "Terminal doesn't support cursor movement\n"); fprintf(term->out, "Terminal doesn't support cursor movement\n");
return 0; return 0;
} }
term->move_relative = _move_relative;
/* Scrolling */ /* Scrolling */
if ((term->TI_csr || term->TI_wind) && term->TI_rin && term->TI_indn) if ((term->TI_csr || term->TI_wind) && term->TI_rin && term->TI_indn)
term->scroll = _scroll_region; term->scroll = _scroll_region;

View File

@ -4,6 +4,7 @@
#include <termios.h> #include <termios.h>
#define terminfo_move(x, y) current_term->move(current_term, x, y) #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_scroll(y1, y2, count) current_term->scroll(current_term, y1, y2, count)
#define terminfo_clear() current_term->clear(current_term) #define terminfo_clear() current_term->clear(current_term)
#define terminfo_clrtoeol() current_term->clrtoeol(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_uline(set) current_term->set_uline(current_term, set)
#define terminfo_set_standout(set) current_term->set_standout(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_has_colors(term) (term->TI_fg[0] != NULL)
#define terminfo_beep(term) current_term->beep(current_term)
typedef struct _TERM_REC TERM_REC; typedef struct _TERM_REC TERM_REC;
struct _TERM_REC { struct _TERM_REC {
/* Functions */ /* Functions */
void (*move)(TERM_REC *term, int x, int y); 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 (*scroll)(TERM_REC *term, int y1, int y2, int count);
void (*clear)(TERM_REC *term); void (*clear)(TERM_REC *term);
@ -45,8 +48,7 @@ struct _TERM_REC {
/* Cursor movement */ /* Cursor movement */
const char *TI_smcup, *TI_rmcup, *TI_cup; const char *TI_smcup, *TI_rmcup, *TI_cup;
const char *TI_hpa, *TI_vpa; const char *TI_hpa, *TI_vpa, *TI_cub1, *TI_cuf1;
int TI_xhpa, TI_xvpa;
/* Scrolling */ /* Scrolling */
const char *TI_csr, *TI_wind; const char *TI_csr, *TI_wind;

View File

@ -307,6 +307,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
char *tmp; char *tmp;
int xpos, color, drawcount, first; 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); cache = textbuffer_view_get_line_cache(view, line);
if (subline >= cache->count) if (subline >= cache->count)
return 0; 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, 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; int linecount;
if (view->dirty) /* don't bother drawing anything - redraw is coming */
return;
while (line != NULL && lines > 0) { while (line != NULL && lines > 0) {
linecount = view_line_draw(view, line, subline, ypos, lines); linecount = view_line_draw(view, line, subline, ypos, lines);
ypos += linecount; lines -= linecount; ypos += linecount; lines -= linecount;
@ -593,17 +599,20 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
line = line->next; line = line->next;
} }
/* clear the rest of the view */ if (fill_bottom) {
term_set_color(view->window, ATTR_RESET); /* clear the rest of the view */
while (lines > 0) { term_set_color(view->window, ATTR_RESET);
term_move(view->window, 0, ypos); while (lines > 0) {
term_clrtoeol(view->window); term_move(view->window, 0, ypos);
ypos++; lines--; term_clrtoeol(view->window);
ypos++; lines--;
}
} }
} }
#define view_draw_top(view, lines) \ #define view_draw_top(view, lines, fill_bottom) \
view_draw(view, (view)->startline, (view)->subline, 0, lines) view_draw(view, (view)->startline, (view)->subline, \
0, lines, fill_bottom)
static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines) 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; line = line->next;
} }
view_draw(view, line, subline, maxline, lines); view_draw(view, line, subline, maxline, lines, TRUE);
} }
/* Returns number of lines actually scrolled */ /* 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 (draw_nonclean) {
if (realcount < 0) if (realcount < 0)
view_draw_top(view, -realcount); view_draw_top(view, -realcount, TRUE);
else else
view_draw_bottom(view, realcount); 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; view->empty_linecount = view->height-linecount;
} }
textbuffer_view_redraw(view); view->dirty = TRUE;
} }
/* Clear the view, don't actually remove any lines from buffer. */ /* 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) { if (view->window != window) {
view->window = window; view->window = window;
if (window != NULL) if (window != NULL)
textbuffer_view_redraw(view); view->dirty = TRUE;
} }
} }
@ -1165,8 +1174,9 @@ void textbuffer_view_redraw(TEXT_BUFFER_VIEW_REC *view)
g_return_if_fail(view != NULL); g_return_if_fail(view != NULL);
if (view->window != NULL) { if (view->window != NULL) {
view->dirty = FALSE;
term_window_clear(view->window); term_window_clear(view->window);
view_draw_top(view, view->height); view_draw_top(view, view->height, FALSE);
term_refresh(view->window); term_refresh(view->window);
} }
} }

View File

@ -71,6 +71,8 @@ struct _TEXT_BUFFER_VIEW_REC {
int empty_linecount; int empty_linecount;
/* window is at the bottom of the text buffer */ /* window is at the bottom of the text buffer */
unsigned int bottom:1; unsigned int bottom:1;
/* Window needs a redraw */
unsigned int dirty:1;
/* Bookmarks to the lines in the buffer - removed automatically /* Bookmarks to the lines in the buffer - removed automatically
when the line gets removed from buffer */ when the line gets removed from buffer */