aboutsummaryrefslogtreecommitdiff
path: root/screen-write.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2008-09-25 20:08:57 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2008-09-25 20:08:57 +0000
commitefe557313aef555b415fa2ea2c9a50c4404ed788 (patch)
tree4a197ade3d901f79bc8b0b990f9756d3da7f5f01 /screen-write.c
parent9edb4d4b85a8714162817f2ae428e654e6bf1f31 (diff)
downloadrtmux-efe557313aef555b415fa2ea2c9a50c4404ed788.tar.gz
rtmux-efe557313aef555b415fa2ea2c9a50c4404ed788.tar.bz2
rtmux-efe557313aef555b415fa2ea2c9a50c4404ed788.zip
Internal screen data rewrite for better 256 colour/UTF-8 support.
Diffstat (limited to 'screen-write.c')
-rw-r--r--screen-write.c737
1 files changed, 382 insertions, 355 deletions
diff --git a/screen-write.c b/screen-write.c
index 35ac3a59..fa64f2a1 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1,4 +1,4 @@
-/* $Id: screen-write.c,v 1.13 2008-09-09 22:16:36 nicm Exp $ */
+/* $Id: screen-write.c,v 1.14 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,17 +22,6 @@
#include "tmux.h"
-#define screen_write_limit(s, v, lower, upper) do { \
- if (v < lower) { \
- v = lower; \
- SCREEN_DEBUG3(s, v, lower, upper); \
- } \
- if (v > upper) { \
- v = upper; \
- SCREEN_DEBUG3(s, v, lower, upper); \
- } \
-} while (0)
-
/* Initialise writing with a window. */
void
screen_write_start_window(struct screen_write_ctx *ctx, struct window *w)
@@ -71,520 +60,558 @@ screen_write_start(struct screen_write_ctx *ctx,
ctx->s = s;
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSOROFF);
+ ctx->write(ctx->data, TTY_CURSORMODE, 0);
}
-/* Finalise writing. */
+/* Finish writing. */
void
screen_write_stop(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
if (ctx->write != NULL && s->mode & MODE_CURSOR)
- ctx->write(ctx->data, TTY_CURSORON);
+ ctx->write(ctx->data, TTY_CURSORMODE, 1);
}
-/* Set screen title. */
+/* Write character. */
void
-screen_write_set_title(struct screen_write_ctx *ctx, char *title)
+screen_write_putc(
+ struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
{
- struct screen *s = ctx->s;
-
- xfree(s->title);
- s->title = title;
+ gc->data = ch;
+ screen_write_cell(ctx, gc);
}
-/* Put a character. */
-void
-screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
+/* Write string. */
+void printflike3
+screen_write_puts(
+ struct screen_write_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
{
- struct screen *s = ctx->s;
- u_short attr;
-
- if (s->cx == screen_size_x(s)) {
- s->cx = 0;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, '\r');
- screen_write_cursor_down_scroll(ctx);
- } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) {
- SCREEN_DEBUG(s);
- return;
- }
- attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
+ va_list ap;
+ char *msg, *ptr;
- screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
- s->cx++;
+ va_start(ap, fmt);
+ xvasprintf(&msg, fmt, ap);
+ va_end(ap);
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, ch);
+ for (ptr = msg; *ptr != '\0'; ptr++)
+ screen_write_putc(ctx, gc, (u_char) *ptr);
+
+ xfree(msg);
}
-/* Put a UTF8 character. */
+/* Copy from another screen. */
void
-screen_write_put_utf8(struct screen_write_ctx *ctx, struct utf8_data *udat)
+screen_write_copy(struct screen_write_ctx *ctx,
+ struct screen *src, u_int px, u_int py, u_int nx, u_int ny)
{
- struct screen *s = ctx->s;
- u_char ch, ch2, fg, bg;
- u_short attr, attr2;
- int idx, wide;
- u_int n;
-
- wide = 0;
- if (udat->data[2] == 0xff)
- n = ((udat->data[0] & 0x1f)<<6) + (udat->data[1] & 0x3f);
- else if (udat->data[3] == 0xff) {
- n = ((udat->data[0] & 0x0f)<<12) +
- ((udat->data[1] & 0x3f)<<6) + (udat->data[2] & 0x3f);
- } else
- n = 0;
- if ((n >= 0x1100 && n <= 0x115f) || n == 0x2329 || n == 0x232a ||
- (n >= 0x2e80 && n <= 0xa4cf && n != 0x303f) ||
- (n >= 0xac00 && n <= 0xd7a3) || (n >= 0xf900 && n <= 0xfaff) ||
- (n >= 0xfe10 && n <= 0xfe19) || (n >= 0xfe30 && n <= 0xfe6f) ||
- (n >= 0xff00 && n <= 0xff60) || (n >= 0xffe0 && n <= 0xffe6) ||
- (n >= 0x20000 && n <= 0x2fffd) || (n >= 0x30000 && n <= 0x3fffd))
- wide = 1;
-
- if (s->cx >= screen_size_x(s) - wide) {
- s->cx = 0;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, '\r');
- screen_write_cursor_down_scroll(ctx);
- } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) {
- SCREEN_DEBUG(s);
- return;
- }
- attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
-
- if ((idx = utf8_add(&s->utf8_table, udat)) == -1)
- ch = '_';
- else {
- utf8_pack(idx, &ch, &attr);
- attr |= ATTR_UTF8;
- }
-
- /* Remove padding before and after, if any. */
- screen_display_get_cell(s, s->cx, s->cy, &ch2, &attr2, &fg, &bg);
- if (s->cx > 0 && (attr2 & ATTR_PAD))
- screen_display_set_cell(s, s->cx - 1, s->cy, ' ', 0, 8, 8);
- if (s->cx < screen_last_x(s) && (attr2 & ATTR_UTF8)) {
- screen_display_get_cell(
- s, s->cx + 1, s->cy, &ch2, &attr2, &fg, &bg);
- if (s->cx > 0 && (attr2 & ATTR_PAD)) {
- screen_display_set_cell(
- s, s->cx + 1, s->cy, ' ', 0, 8, 8);
+ struct screen *s = ctx->s;
+ struct grid_data *gd = src->grid;
+ const struct grid_cell *gc;
+ u_int xx, yy, cx, cy;
+
+ cx = s->cx;
+ cy = s->cy;
+ for (yy = py; yy < py + ny; yy++) {
+ for (xx = px; xx < px + nx; xx++) {
+ if (xx >= gd->sx || yy >= gd->hsize + gd->sy)
+ gc = &grid_default_cell;
+ else
+ gc = grid_peek_cell(gd, xx, yy);
+ screen_write_cell(ctx, gc);
}
- }
-
- screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
- s->cx++;
-
- if (wide) {
- screen_display_set_cell(s, s->cx, s->cy, ' ', ATTR_PAD, 8, 8);
- s->cx++;
- }
-
- if (ctx->write != NULL) {
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, s->fg, s->bg);
- ctx->write(ctx->data, TTY_CHARACTER, ch);
- ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
+ cy++;
+ screen_write_cursormove(ctx, cx, cy);
}
}
-/* Put a string right-justified. */
-size_t printflike2
-screen_write_put_string_rjust(
- struct screen_write_ctx *ctx, const char *fmt, ...)
+/* Cursor up by ny. */
+void
+screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- va_list ap;
- size_t size;
- char *msg, *ptr;
- va_start(ap, fmt);
- size = vasprintf(&msg, fmt, ap);
- va_end(ap);
+ if (ny > s->cy)
+ ny = s->cy;
+ if (ny == 0)
+ ny = 1;
- ptr = msg;
- if (size > screen_size_x(s)) {
- ptr += size - screen_size_x(s);
- size = screen_size_x(s);
- }
- screen_write_move_cursor(ctx, screen_size_x(s) - size, s->cy);
- for (; *ptr != '\0'; ptr++) {
- if (s->cx == screen_size_x(s))
- break;
- screen_write_put_character(ctx, *ptr);
- }
+ s->cy -= ny;
- xfree(msg);
-
- return (size);
+ if (ctx != NULL)
+ ctx->write(ctx->data, TTY_CURSORUP, ny);
}
-/* Put a string, truncating at end of line. */
-void printflike2
-screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...)
+/* Cursor down by ny. */
+void
+screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- va_list ap;
- char *msg, *ptr;
- va_start(ap, fmt);
- vasprintf(&msg, fmt, ap);
- va_end(ap);
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
+
+ s->cy += ny;
- for (ptr = msg; *ptr != '\0'; ptr++) {
- if (s->cx == screen_size_x(s))
- break;
- screen_write_put_character(ctx, *ptr);
- }
-
- xfree(msg);
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORDOWN, ny);
}
-/* Set screen attributes. */
+/* Cursor right by nx. */
void
-screen_write_set_attributes(
- struct screen_write_ctx *ctx, u_short attr, u_char fg, u_char bg)
+screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
- if (s->attr != attr || s->fg != fg || s->bg != bg) {
- s->attr = attr;
- s->fg = fg;
- s->bg = bg;
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
- }
+ s->cx += nx;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORRIGHT, nx);
}
-/* Set scroll region. */
+/* Cursor left by nx. */
void
-screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower)
+screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, upper, 0, screen_last_y(s));
- screen_write_limit(s, lower, 0, screen_last_y(s));
- if (upper > lower) {
- SCREEN_DEBUG2(s, upper, lower);
- return;
- }
-
- /* Cursor moves to top-left. */
- s->cx = 0;
- s->cy = upper;
-
- s->rupper = upper;
- s->rlower = lower;
-
+
+ if (nx > s->cx)
+ nx = s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ s->cx -= nx;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
+ ctx->write(ctx->data, TTY_CURSORLEFT, nx);
}
-/* Move cursor up and scroll if necessary. */
+/* Insert nx characters. */
void
-screen_write_cursor_up_scroll(struct screen_write_ctx *ctx)
+screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- if (s->cy == s->rupper)
- screen_display_scroll_region_down(s);
- else if (s->cy > 0)
- s->cy--;
-
+
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_REVERSEINDEX);
+ ctx->write(ctx->data, TTY_INSERTCHARACTER, nx);
}
-/* Move cursor down and scroll if necessary */
+/* Delete nx characters. */
void
-screen_write_cursor_down_scroll(struct screen_write_ctx *ctx)
+screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- if (s->cy == s->rlower)
- screen_display_scroll_region_up(s);
- else if (s->cy < screen_last_y(s))
- s->cy++;
-
- if (ctx->write != NULL) /* XXX FORWARDINDEX */
- ctx->write(ctx->data, TTY_CHARACTER, '\n');
+
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_DELETECHARACTER, nx);
}
-/* Move cursor up. */
+/* Insert ny lines. */
void
-screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n)
+screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- screen_write_limit(s, n, 1, screen_above_y(s, s->cy) - 1);
-
- s->cy -= n;
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
+ if (s->cy < s->rupper || s->cy > s->rlower)
+ grid_view_insert_lines(s->grid, s->cy, ny);
+ else {
+ grid_view_insert_lines_region(
+ s->grid, s->rupper, s->rlower, s->cy, ny);
+ }
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_INSERTLINE, ny);
}
-/* Move cursor down. */
+/* Delete ny lines. */
void
-screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n)
+screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy) - 1);
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
- s->cy += n;
+ if (s->cy < s->rupper || s->cy > s->rlower)
+ grid_view_delete_lines(s->grid, s->cy, ny);
+ else {
+ grid_view_delete_lines_region(
+ s->grid, s->rupper, s->rlower, s->cy, ny);
+ }
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_DELETELINE, ny);
}
-/* Move cursor left. */
+/* Clear line at cursor. */
void
-screen_write_cursor_left(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_left_x(s, s->cx) - 1);
-
- s->cx -= n;
-
+
+ grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_CLEARLINE);
}
-/* Move cursor right. */
+/* Clear to end of line from cursor. */
void
-screen_write_cursor_right(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearendofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx) - 1);
-
- s->cx += n;
-
+
+ grid_view_clear(s->grid, s->cx, s->cy, screen_size_x(s) - s->cx, 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
-/* Delete lines. */
+/* Clear to start of line from cursor. */
void
-screen_write_delete_lines(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearstartofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
+
+ grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CLEARSTARTOFLINE);
+}
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy));
+/* Move cursor to px,py. */
+void
+screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
+{
+ struct screen *s = ctx->s;
+
+ if (px > screen_size_x(s) - 1)
+ px = screen_size_x(s) - 1;
+ if (py > screen_size_y(s) - 1)
+ py = screen_size_y(s) - 1;
+
+ s->cx = px;
+ s->cy = py;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORMOVE, px, py);
+}
- if (s->cy < s->rupper || s->cy > s->rlower)
- screen_display_delete_lines(s, s->cy, n);
+/* Set cursor mode. */
+void
+screen_write_cursormode(struct screen_write_ctx *ctx, int state)
+{
+ struct screen *s = ctx->s;
+
+ if (state)
+ s->mode |= MODE_CURSOR;
else
- screen_display_delete_lines_region(s, s->cy, n);
-
+ s->mode &= ~MODE_CURSOR;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_DELETELINE, n);
+ ctx->write(ctx->data, TTY_CURSORMODE, state);
}
-/* Delete characters. */
+/* Reverse index (up with scroll). */
void
-screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n)
+screen_write_reverseindex(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
+
+ if (s->cy == s->rupper)
+ grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
+ else if (s->cy > 0)
+ s->cy--;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_REVERSEINDEX);
+}
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx));
+/* Set scroll region. */
+void
+screen_write_scrollregion(
+ struct screen_write_ctx *ctx, u_int rupper, u_int rlower)
+{
+ struct screen *s = ctx->s;
+
+ if (rupper > screen_size_y(s) - 1)
+ rupper = screen_size_y(s) - 1;
+ if (rlower > screen_size_y(s) - 1)
+ rlower = screen_size_y(s) - 1;
+ if (rupper > rlower)
+ return;
- screen_display_delete_characters(s, s->cx, s->cy, n);
+ /* Cursor moves to top-left. */
+ s->cx = 0;
+ s->cy = rupper;
+ s->rupper = rupper;
+ s->rlower = rlower;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_DELETECHARACTER, n);
+ ctx->write(ctx->data, TTY_SCROLLREGION, rupper, rlower);
}
-/* Insert lines. */
+/* Set insert mode. */
void
-screen_write_insert_lines(struct screen_write_ctx *ctx, u_int n)
+screen_write_insertmode(struct screen_write_ctx *ctx, int state)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy));
-
- if (s->cy < s->rupper || s->cy > s->rlower)
- screen_display_insert_lines(s, s->cy, n);
+
+ if (state)
+ s->mode |= MODE_INSERT;
else
- screen_display_insert_lines_region(s, s->cy, n);
-
+ s->mode &= ~MODE_INSERT;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_INSERTLINE, n);
+ ctx->write(ctx->data, TTY_INSERTMODE, state);
}
-/* Insert characters. */
+/* Set mouse mode. */
void
-screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n)
+screen_write_mousemode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx));
-
- screen_display_insert_characters(s, s->cx, s->cy, n);
+ struct screen *s = ctx->s;
+ if (state)
+ s->mode |= MODE_MOUSE;
+ else
+ s->mode &= ~MODE_MOUSE;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_INSERTCHARACTER, n);
+ ctx->write(ctx->data, TTY_MOUSEMODE, state);
}
-/* Move the cursor. */
+/* Line feed (down with scroll). */
void
-screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m)
+screen_write_linefeed(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 0, screen_last_x(s));
- screen_write_limit(s, m, 0, screen_last_y(s));
-
- s->cx = n;
- s->cy = m;
-
+ struct screen *s = ctx->s;
+
+ if (s->cy == s->rlower)
+ grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
+ else if (s->cy < screen_size_x(s) - 1)
+ s->cy++;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_LINEFEED);
}
-/* Full to end of screen. */
+/* Carriage return (cursor to start of line). */
void
-screen_write_fill_end_of_screen(struct screen_write_ctx *ctx)
+screen_write_carriagereturn(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- u_int i;
-
- screen_display_fill_area(s, s->cx, s->cy,
- screen_right_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
- screen_display_fill_area(s, 0, s->cy + 1, screen_size_x(s),
- screen_below_y(s, s->cy + 1), ' ', s->attr, s->fg, s->bg);
+ struct screen *s = ctx->s;
+
+ s->cx = 0;
- if (ctx->write != NULL) {
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- for (i = s->cy + 1; i < screen_size_y(s); i++) {
- ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- }
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
- }
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CARRIAGERETURN);
}
-/* Fill entire screen. */
+/* Set keypad cursor keys mode. */
void
-screen_write_fill_screen(struct screen_write_ctx *ctx)
+screen_write_kcursormode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
- u_int i;
-
- screen_display_fill_area(s, 0, 0,
- screen_size_x(s), screen_size_y(s), ' ', s->attr, s->fg, s->bg);
-
- if (ctx->write != NULL) {
- for (i = 0; i < screen_size_y(s); i++) {
- ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- }
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
- }
+ struct screen *s = ctx->s;
+
+ if (state)
+ s->mode |= MODE_KCURSOR;
+ else
+ s->mode &= ~MODE_KCURSOR;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_KCURSORMODE);
}
-/* Fill to end of line. */
+/* Set keypad number keys mode. */
void
-screen_write_fill_end_of_line(struct screen_write_ctx *ctx)
+screen_write_kkeypadmode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
-
- screen_display_fill_area(s, s->cx, s->cy,
- screen_right_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
+ struct screen *s = ctx->s;
+ if (state)
+ s->mode |= MODE_KKEYPAD;
+ else
+ s->mode &= ~MODE_KKEYPAD;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
+ ctx->write(ctx->data, TTY_KKEYPADMODE);
}
-/* Fill to start of line. */
+/* Clear to end of screen from cursor. */
void
-screen_write_fill_start_of_line(struct screen_write_ctx *ctx)
+screen_write_clearendofscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ u_int sx, sy;
- screen_display_fill_area(s, 0, s->cy,
- screen_left_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
+ sx = screen_size_x(s);
+ sy = screen_size_y(s);
+ grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARSTARTOFLINE);
+ ctx->write(ctx->data, TTY_CLEARENDOFSCREEN);
}
-/* Fill entire line. */
+/* Clear to start of screen. */
void
-screen_write_fill_line(struct screen_write_ctx *ctx)
+screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ u_int sx, sy;
- screen_display_fill_area(
- s, 0, s->cy, screen_size_x(s), s->cy, ' ', s->attr, s->fg, s->bg);
+ sx = screen_size_x(s);
+ sy = screen_size_y(s);
+ if (s->cy > 0)
+ grid_view_clear(s->grid, 0, 0, sx, s->cy - 1);
+ grid_view_clear(s->grid, 0, s->cy, s->cx, 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARLINE);
+ ctx->write(ctx->data, TTY_CLEARSTARTOFSCREEN);
}
-/* Set a screen mode. */
+/* Clear entire screen. */
void
-screen_write_set_mode(struct screen_write_ctx *ctx, int mode)
+screen_write_clearscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
-
- s->mode |= mode;
-
- if (ctx->write == NULL)
- return;
+ struct screen *s = ctx->s;
- if (mode & MODE_INSERT)
- ctx->write(ctx->data, TTY_INSERTON);
- if (mode & MODE_MOUSE)
- ctx->write(ctx->data, TTY_MOUSEON);
+ grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CLEARSCREEN);
}
-/* Clear a screen mode. */
+/* Write cell data. */
void
-screen_write_clear_mode(struct screen_write_ctx *ctx, int mode)
+screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ struct grid_data *gd = s->grid;
+ u_int width, xx;
+ const struct grid_cell *hc;
+ struct grid_cell *ic, tc;
- s->mode &= ~mode;
+ width = utf8_width(gc->data);
- if (ctx->write == NULL)
- return;
+ /* If the character is wider than the screen, don't print it. */
+ if (width > screen_size_x(s)) {
+ memcpy(&tc, gc, sizeof tc);
+ tc.data = '_';
- if (mode & MODE_INSERT)
- ctx->write(ctx->data, TTY_INSERTOFF);
- if (mode & MODE_MOUSE)
- ctx->write(ctx->data, TTY_MOUSEOFF);
-}
+ width = 1;
+ gc = &tc;
+ }
+
+ /* Check this will fit on the current line; scroll if not. */
+ if (s->cx >= screen_size_x(s) + 1 - width) {
+ screen_write_carriagereturn(ctx);
+ screen_write_linefeed(ctx);
+ }
-/* Copy cells from another screen. */
-void
-screen_write_copy_area(struct screen_write_ctx *ctx,
- struct screen *src, u_int nx, u_int ny, u_int ox, u_int oy)
-{
- struct screen *s = ctx->s;
- struct screen_redraw_ctx rctx;
- int saved_mode;
+ /* Sanity checks. */
+ if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
+ return;
- screen_write_limit(s, nx, 1, screen_right_x(s, s->cx));
- screen_write_limit(s, ny, 1, screen_below_y(s, s->cy));
+ /*
+ * UTF-8 wide characters are a bit of an annoyance. They take up more
+ * than one cell on the screen, so following cells must not be drawn by
+ * marking them as padding.
+ *
+ * So far, so good. The problem is, when overwriting a padding cell, or
+ * a UTF-8 character, it is necessary to also overwrite any other cells
+ * which covered by the same character.
+ */
+ hc = grid_view_peek_cell(gd, s->cx, s->cy);
+ if (hc->flags & GRID_FLAG_PADDING) {
+ /*
+ * A padding cell, so clear any following and leading padding
+ * cells back to the character. Don't overwrite the current
+ * cell as that happens later anyway.
+ */
+ xx = s->cx;
+ while (xx-- > 0) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
- screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy);
+ /* Overwrite the character at the start of this padding. */
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
- if (ctx->write != NULL) {
- /* Save mode XXX hack */
- saved_mode = ctx->s->mode;
- ctx->s->mode &= ~MODE_CURSOR;
+ /* Overwrite following padding cells. */
+ xx = s->cx;
+ while (++xx < screen_size_x(s)) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
+ } else if (utf8_width(hc->data) > 1) {
+ /*
+ * An UTF-8 wide cell; overwrite following padding cells only.
+ */
+ xx = s->cx;
+ while (++xx < screen_size_x(s)) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
+ }
- screen_redraw_start(&rctx, ctx->s, ctx->write, ctx->data);
- screen_redraw_area(&rctx, s->cx, s->cy, nx, ny);
- screen_redraw_stop(&rctx);
+ /*
+ * If the new character is UTF-8 wide, fill in padding cells. Have
+ * already ensured there is enough room.
+ */
+ for (xx = s->cx + 1; xx < s->cx + width; xx++) {
+ ic = grid_view_get_cell(gd, xx, s->cy);
+ ic->flags |= GRID_FLAG_PADDING;
+ }
- ctx->s->mode = saved_mode;
+ /* Write the actual cell. */
+ grid_view_set_cell(gd, s->cx, s->cy, gc);
+ s->cx += width;
+
+ if (ctx->write != NULL) {
+ if (screen_check_selection(ctx->s, s->cx, s->cy)) {
+ memcpy(&tc, gc, sizeof tc);
+ tc.attr |= GRID_ATTR_REVERSE;
+ ctx->write(ctx->data, TTY_CELL, &tc);
+ } else
+ ctx->write(ctx->data, TTY_CELL, gc);
}
}