1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-16 06:25:24 +00: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 */
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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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();

View File

@ -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)
{

View File

@ -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);

View File

@ -4,3 +4,4 @@
extern int quitting;
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) {
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;
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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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 */