summaryrefslogtreecommitdiff
path: root/src/fe-text
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2001-10-28 18:40:12 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2001-10-28 18:40:12 +0000
commitfb439b5c2ae93e0d42a59cf8900a17cbb72214f6 (patch)
tree604d6da2c3a9dcbbf33c72245043d7b8b6863fa0 /src/fe-text
parent44b12481d66c68e00f5dade2a0fc815497b1535c (diff)
downloadirssi-fb439b5c2ae93e0d42a59cf8900a17cbb72214f6.zip
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
Diffstat (limited to 'src/fe-text')
-rw-r--r--src/fe-text/gui-entry.c35
-rw-r--r--src/fe-text/gui-entry.h4
-rw-r--r--src/fe-text/gui-windows.c14
-rw-r--r--src/fe-text/irssi.c50
-rw-r--r--src/fe-text/mainwindows.c57
-rw-r--r--src/fe-text/mainwindows.h7
-rw-r--r--src/fe-text/module.h1
-rw-r--r--src/fe-text/statusbar-config.c2
-rw-r--r--src/fe-text/statusbar-items.c20
-rw-r--r--src/fe-text/statusbar.c142
-rw-r--r--src/fe-text/statusbar.h10
-rw-r--r--src/fe-text/term-terminfo.c38
-rw-r--r--src/fe-text/terminfo-core.c43
-rw-r--r--src/fe-text/terminfo-core.h6
-rw-r--r--src/fe-text/textbuffer-view.c40
-rw-r--r--src/fe-text/textbuffer-view.h2
16 files changed, 348 insertions, 123 deletions
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index f3f2463e..77cd0f02 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -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);
}
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index 0c2b4a4b..70bccb55 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -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;
diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c
index 5c6f00e5..1ce50fb6 100644
--- a/src/fe-text/gui-windows.c
+++ b/src/fe-text/gui-windows.c
@@ -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)
diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c
index e625e595..863adfd3 100644
--- a/src/fe-text/irssi.c
+++ b/src/fe-text/irssi.c
@@ -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();
diff --git a/src/fe-text/mainwindows.c b/src/fe-text/mainwindows.c
index 0d1c3f19..c849f6cd 100644
--- a/src/fe-text/mainwindows.c
+++ b/src/fe-text/mainwindows.c
@@ -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)
{
diff --git a/src/fe-text/mainwindows.h b/src/fe-text/mainwindows.h
index 6306758f..1bca333d 100644
--- a/src/fe-text/mainwindows.h
+++ b/src/fe-text/mainwindows.h
@@ -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);
diff --git a/src/fe-text/module.h b/src/fe-text/module.h
index ba5888ad..c6643545 100644
--- a/src/fe-text/module.h
+++ b/src/fe-text/module.h
@@ -4,3 +4,4 @@
extern int quitting;
void irssi_redraw(void);
+void irssi_set_dirty(void);
diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c
index f703afa7..390ce193 100644
--- a/src/fe-text/statusbar-config.c
+++ b/src/fe-text/statusbar-config.c
@@ -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);
}
}
}
diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c
index 70547daf..da485d5b 100644
--- a/src/fe-text/statusbar-items.c
+++ b/src/fe-text/statusbar-items.c
@@ -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)
diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c
index 0ed75fed..5ca83f70 100644
--- a/src/fe-text/statusbar.c
+++ b/src/fe-text/statusbar.c
@@ -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);
}
}
diff --git a/src/fe-text/statusbar.h b/src/fe-text/statusbar.h
index 08e9ba80..0d61c059 100644
--- a/src/fe-text/statusbar.h
+++ b/src/fe-text/statusbar.h
@@ -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);
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 1f0e8974..bf9fd22e 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -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);
}
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index 08c76d10..3dee2ffc 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -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;
diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h
index 480e80c1..4586178d 100644
--- a/src/fe-text/terminfo-core.h
+++ b/src/fe-text/terminfo-core.h
@@ -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;
diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c
index cc33f715..540721e7 100644
--- a/src/fe-text/textbuffer-view.c
+++ b/src/fe-text/textbuffer-view.c
@@ -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);
}
}
diff --git a/src/fe-text/textbuffer-view.h b/src/fe-text/textbuffer-view.h
index e8b1262d..497a980d 100644
--- a/src/fe-text/textbuffer-view.h
+++ b/src/fe-text/textbuffer-view.h
@@ -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 */