summaryrefslogtreecommitdiff
path: root/src/fe-text/term-terminfo.c
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2001-11-03 15:31:13 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2001-11-03 15:31:13 +0000
commit3578cea2584409a178f93592cc9a004566d2bc84 (patch)
treefb6229bf633d9b975064c4b8841ac402c2f318e9 /src/fe-text/term-terminfo.c
parentd4d72e5583827c86d047de576917fd30b7566275 (diff)
downloadirssi-3578cea2584409a178f93592cc9a004566d2bc84.zip
Virtualized cursor movement and clearing to end of line. Now neither is done
unless really needed. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1966 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/fe-text/term-terminfo.c')
-rw-r--r--src/fe-text/term-terminfo.c127
1 files changed, 102 insertions, 25 deletions
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 6e462284..7427985b 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -36,8 +36,10 @@ struct _TERM_WINDOW {
TERM_WINDOW *root_window;
int term_width, term_height;
+char *term_lines_empty; /* 1 if line is entirely empty */
-static int vcx, vcy, curs_visible;
+static int vcmove, vcx, vcy, curs_visible;
+static int crealx, crealy, cforcemove;
static int curs_x, curs_y;
static int last_fg, last_bg, last_attrs;
static int redraw_needed, redraw_tag;
@@ -66,7 +68,8 @@ int term_init(void)
last_fg = last_bg = -1;
last_attrs = 0;
- vcx = vcy = -1;
+ vcx = vcy = 0; crealx = crealy = -1;
+ vcmove = FALSE; cforcemove = TRUE;
curs_visible = TRUE;
current_term = terminfo_core_init(stdin, stdout);
@@ -85,6 +88,8 @@ int term_init(void)
term_height = current_term->height;
root_window = term_window_create(0, 0, term_width, term_height);
+ term_lines_empty = g_new0(char, term_height);
+
term_common_init();
return TRUE;
}
@@ -97,6 +102,36 @@ void term_deinit(void)
terminfo_core_deinit(current_term);
}
+static void term_move_real(void)
+{
+ if (vcx != crealx || vcy != crealy || cforcemove) {
+ if (curs_visible) {
+ terminfo_set_cursor_visible(FALSE);
+ curs_visible = FALSE;
+ }
+
+ if (cforcemove) {
+ crealx = crealy = -1;
+ cforcemove = FALSE;
+ }
+ terminfo_move_relative(crealx, crealy, vcx, vcy);
+ crealx = vcx; crealy = vcy;
+ }
+
+ vcmove = FALSE;
+}
+
+/* Cursor position is unknown - move it immediately to known position */
+static void term_move_reset(int x, int y)
+{
+ if (x >= term_width) x = term_width-1;
+ if (y >= term_height) y = term_height-1;
+
+ vcx = x; vcy = y;
+ cforcemove = TRUE;
+ term_move_real();
+}
+
/* Resize terminal - if width or height is negative,
the new size is unknown and should be figured out somehow */
void term_resize(int width, int height)
@@ -110,10 +145,13 @@ void term_resize(int width, int height)
if (term_width != width || term_height != height) {
term_width = current_term->width = width;
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);
+
+ g_free(term_lines_empty);
+ term_lines_empty = g_new0(char, term_height);
}
- vcx = vcy = -1;
+ term_move_reset(0, 0);
}
void term_resize_final(int width, int height)
@@ -135,9 +173,11 @@ void term_force_colors(int set)
/* Clear screen */
void term_clear(void)
{
- vcx = vcy = -1;
term_set_color(root_window, 0);
- terminfo_clear();
+ terminfo_clear();
+ term_move_reset(0, 0);
+
+ memset(term_lines_empty, 1, term_height);
}
/* Beep */
@@ -193,8 +233,24 @@ void term_window_clear(TERM_WINDOW *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);
+ int y, idx;
+
+ terminfo_scroll(window->y, window->y+window->height-1, count);
+
+ /* set the newly scrolled lines dirty */
+ if (count < 0) {
+ /* scrolling down - dirty the top */
+ idx = window->y;
+ count = -count;
+ } else {
+ /* scrolling up - dirty the bottom */
+ idx = window->y+window->height-count;
+ }
+
+ for (y = 0; y < count; y++)
+ term_lines_empty[idx+y] = FALSE;
+
+ term_move_reset(vcx, vcy);
}
/* Change active color */
@@ -265,43 +321,63 @@ void term_set_color(TERM_WINDOW *window, int col)
void term_move(TERM_WINDOW *window, int x, int y)
{
- int newx, newy;
-
- if (curs_visible) {
- terminfo_set_cursor_visible(FALSE);
- curs_visible = FALSE;
- }
+ vcmove = TRUE;
+ vcx = x+window->x;
+ vcy = y+window->y;
+
+ if (vcx >= term_width)
+ vcx = term_width-1;
+ if (vcy >= term_height)
+ vcy = term_height-1;
+}
- newx = x+window->x;
- newy = y+window->y;
- if (vcx != newx || vcy != newy) {
- terminfo_move_relative(vcx, vcy, newx, newy);
- vcx = newx; vcy = newy;
+static void term_printed_text(int count)
+{
+ term_lines_empty[vcy] = FALSE;
+
+ /* if we continued writing past the line, wrap to next line.
+ However, next term_move() really shouldn't try to cache
+ the move, otherwise terminals would try to combine the
+ last word in upper line with first word in lower line. */
+ cforcemove = TRUE;
+ vcx += count;
+ while (vcx >= term_width) {
+ vcx -= term_width;
+ if (vcy < term_height) vcy++;
+ if (vcx > 0) term_lines_empty[vcy] = FALSE;
}
}
void term_addch(TERM_WINDOW *window, int chr)
{
+ if (vcmove) term_move_real();
putc(chr, window->term->out);
- vcx++; /* ignore if cursor gets past the screen */
+ term_printed_text(1);
}
void term_addstr(TERM_WINDOW *window, char *str)
{
+ if (vcmove) term_move_real();
fputs(str, window->term->out);
- vcx += strlen(str); /* ignore if cursor gets past the screen */
+ term_printed_text(strlen(str));
}
void term_clrtoeol(TERM_WINDOW *window)
{
+ /* clrtoeol() doesn't necessarily understand colors */
if (last_fg == -1 && last_bg == -1 &&
(last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE)) == 0) {
- /* clrtoeol() doesn't necessarily understand colors */
- terminfo_clrtoeol();
+ if (!term_lines_empty[vcy]) {
+ if (vcmove) term_move_real();
+ terminfo_clrtoeol();
+ if (vcx == 0) term_lines_empty[vcy] = TRUE;
+ }
} else if (vcx < term_width) {
/* we'll need to fill the line ourself. */
+ if (vcmove) term_move_real();
terminfo_repeat(' ', term_width-vcx);
terminfo_move(vcx, vcy);
+ term_lines_empty[vcy] = FALSE;
}
}
@@ -316,8 +392,9 @@ void term_refresh(TERM_WINDOW *window)
if (freeze_counter > 0)
return;
- if (vcx != curs_x || vcy != curs_y)
- term_move(root_window, curs_x, curs_y);
+ term_move(root_window, curs_x, curs_y);
+ term_move_real();
+
if (!curs_visible) {
terminfo_set_cursor_visible(TRUE);
curs_visible = TRUE;