version 1.138, 2018/07/31 11:49:26 |
version 1.139, 2018/10/18 08:38:01 |
|
|
TAILQ_HEAD(, screen_write_collect_item) items; |
TAILQ_HEAD(, screen_write_collect_item) items; |
}; |
}; |
|
|
|
static void |
|
screen_write_offset_timer(__unused int fd, __unused short events, void *data) |
|
{ |
|
struct window *w = data; |
|
|
|
tty_update_window_offset(w); |
|
} |
|
|
|
/* Set cursor position. */ |
|
static void |
|
screen_write_set_cursor(struct screen_write_ctx *ctx, int cx, int cy) |
|
{ |
|
struct window_pane *wp = ctx->wp; |
|
struct window *w; |
|
struct screen *s = ctx->s; |
|
struct timeval tv = { .tv_usec = 10000 }; |
|
|
|
if (cx != -1 && (u_int)cx == s->cx && cy != -1 && (u_int)cy == s->cy) |
|
return; |
|
|
|
if (cx != -1) |
|
s->cx = cx; |
|
if (cy != -1) |
|
s->cy = cy; |
|
|
|
if (wp == NULL) |
|
return; |
|
w = wp->window; |
|
|
|
if (!event_initialized(&w->offset_timer)) |
|
evtimer_set(&w->offset_timer, screen_write_offset_timer, w); |
|
if (!evtimer_pending(&w->offset_timer, NULL)) |
|
evtimer_add(&w->offset_timer, &tv); |
|
} |
|
|
/* Initialize writing with a window. */ |
/* Initialize writing with a window. */ |
void |
void |
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp, |
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp, |
struct screen *s) |
struct screen *s) |
{ |
{ |
char tmp[16]; |
char tmp[32]; |
u_int y; |
u_int y; |
|
|
memset(ctx, 0, sizeof *ctx); |
memset(ctx, 0, sizeof *ctx); |
|
|
ctx->scrolled = 0; |
ctx->scrolled = 0; |
ctx->bg = 8; |
ctx->bg = 8; |
|
|
if (wp != NULL) |
if (wp != NULL) { |
snprintf(tmp, sizeof tmp, "pane %%%u", wp->id); |
snprintf(tmp, sizeof tmp, "pane %%%u (at %u,%u)", wp->id, |
|
wp->xoff, wp->yoff); |
|
} |
log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s), |
log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s), |
screen_size_y(ctx->s), wp == NULL ? "no pane" : tmp); |
screen_size_y(ctx->s), wp == NULL ? "no pane" : tmp); |
} |
} |
|
|
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny) |
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny) |
{ |
{ |
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
|
u_int cx = s->cx, cy = s->cy; |
|
|
if (ny == 0) |
if (ny == 0) |
ny = 1; |
ny = 1; |
|
|
if (s->cy < s->rupper) { |
if (cy < s->rupper) { |
/* Above region. */ |
/* Above region. */ |
if (ny > s->cy) |
if (ny > cy) |
ny = s->cy; |
ny = cy; |
} else { |
} else { |
/* Below region. */ |
/* Below region. */ |
if (ny > s->cy - s->rupper) |
if (ny > cy - s->rupper) |
ny = s->cy - s->rupper; |
ny = cy - s->rupper; |
} |
} |
if (s->cx == screen_size_x(s)) |
if (cx == screen_size_x(s)) |
s->cx--; |
cx--; |
if (ny == 0) |
|
return; |
|
|
|
s->cy -= ny; |
cy -= ny; |
|
|
|
screen_write_set_cursor(ctx, cx, cy); |
} |
} |
|
|
/* Cursor down by ny. */ |
/* Cursor down by ny. */ |
|
|
screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny) |
screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny) |
{ |
{ |
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
|
u_int cx = s->cx, cy = s->cy; |
|
|
if (ny == 0) |
if (ny == 0) |
ny = 1; |
ny = 1; |
|
|
if (s->cy > s->rlower) { |
if (cy > s->rlower) { |
/* Below region. */ |
/* Below region. */ |
if (ny > screen_size_y(s) - 1 - s->cy) |
if (ny > screen_size_y(s) - 1 - cy) |
ny = screen_size_y(s) - 1 - s->cy; |
ny = screen_size_y(s) - 1 - cy; |
} else { |
} else { |
/* Above region. */ |
/* Above region. */ |
if (ny > s->rlower - s->cy) |
if (ny > s->rlower - cy) |
ny = s->rlower - s->cy; |
ny = s->rlower - cy; |
} |
} |
if (s->cx == screen_size_x(s)) |
if (cx == screen_size_x(s)) |
s->cx--; |
cx--; |
if (ny == 0) |
else if (ny == 0) |
return; |
return; |
|
|
s->cy += ny; |
cy += ny; |
|
|
|
screen_write_set_cursor(ctx, cx, cy); |
} |
} |
|
|
/* Cursor right by nx. */ |
/* Cursor right by nx. */ |
|
|
screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx) |
screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx) |
{ |
{ |
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
|
u_int cx = s->cx, cy = s->cy; |
|
|
if (nx == 0) |
if (nx == 0) |
nx = 1; |
nx = 1; |
|
|
if (nx > screen_size_x(s) - 1 - s->cx) |
if (nx > screen_size_x(s) - 1 - cx) |
nx = screen_size_x(s) - 1 - s->cx; |
nx = screen_size_x(s) - 1 - cx; |
if (nx == 0) |
if (nx == 0) |
return; |
return; |
|
|
s->cx += nx; |
cx += nx; |
|
|
|
screen_write_set_cursor(ctx, cx, cy); |
} |
} |
|
|
/* Cursor left by nx. */ |
/* Cursor left by nx. */ |
|
|
screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx) |
screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx) |
{ |
{ |
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
|
u_int cx = s->cx, cy = s->cy; |
|
|
if (nx == 0) |
if (nx == 0) |
nx = 1; |
nx = 1; |
|
|
if (nx > s->cx) |
if (nx > cx) |
nx = s->cx; |
nx = cx; |
if (nx == 0) |
if (nx == 0) |
return; |
return; |
|
|
s->cx -= nx; |
cx -= nx; |
|
|
|
screen_write_set_cursor(ctx, cx, cy); |
} |
} |
|
|
/* Backspace; cursor left unless at start of wrapped line when can move up. */ |
/* Backspace; cursor left unless at start of wrapped line when can move up. */ |
|
|
{ |
{ |
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
struct grid_line *gl; |
struct grid_line *gl; |
|
u_int cx = s->cx, cy = s->cy; |
|
|
if (s->cx == 0) { |
if (cx == 0) { |
if (s->cy == 0) |
if (cy == 0) |
return; |
return; |
gl = grid_get_line(s->grid, s->grid->hsize + s->cy - 1); |
gl = grid_get_line(s->grid, s->grid->hsize + cy - 1); |
if (gl->flags & GRID_LINE_WRAPPED) { |
if (gl->flags & GRID_LINE_WRAPPED) { |
s->cy--; |
cy--; |
s->cx = screen_size_x(s) - 1; |
cx = screen_size_x(s) - 1; |
} |
} |
} else |
} else |
s->cx--; |
cx--; |
|
|
|
screen_write_set_cursor(ctx, cx, cy); |
} |
} |
|
|
/* VT100 alignment test. */ |
/* VT100 alignment test. */ |
|
|
struct grid_cell gc; |
struct grid_cell gc; |
u_int xx, yy; |
u_int xx, yy; |
|
|
screen_write_initctx(ctx, &ttyctx); |
|
|
|
memcpy(&gc, &grid_default_cell, sizeof gc); |
memcpy(&gc, &grid_default_cell, sizeof gc); |
utf8_set(&gc.data, 'E'); |
utf8_set(&gc.data, 'E'); |
|
|
|
|
grid_view_set_cell(s->grid, xx, yy, &gc); |
grid_view_set_cell(s->grid, xx, yy, &gc); |
} |
} |
|
|
s->cx = 0; |
screen_write_set_cursor(ctx, 0, 0); |
s->cy = 0; |
|
|
|
s->rupper = 0; |
s->rupper = 0; |
s->rlower = screen_size_y(s) - 1; |
s->rlower = screen_size_y(s) - 1; |
|
|
if (py > screen_size_y(s) - 1) |
if (py > screen_size_y(s) - 1) |
py = screen_size_y(s) - 1; |
py = screen_size_y(s) - 1; |
|
|
s->cx = px; |
screen_write_set_cursor(ctx, px, py); |
s->cy = py; |
|
} |
} |
|
|
/* Reverse index (up with scroll). */ |
/* Reverse index (up with scroll). */ |
|
|
if (s->cy == s->rupper) |
if (s->cy == s->rupper) |
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); |
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); |
else if (s->cy > 0) |
else if (s->cy > 0) |
s->cy--; |
screen_write_set_cursor(ctx, -1, s->cy - 1); |
|
|
screen_write_collect_flush(ctx, 0); |
screen_write_collect_flush(ctx, 0); |
tty_write(tty_cmd_reverseindex, &ttyctx); |
tty_write(tty_cmd_reverseindex, &ttyctx); |
|
|
screen_write_collect_flush(ctx, 0); |
screen_write_collect_flush(ctx, 0); |
|
|
/* Cursor moves to top-left. */ |
/* Cursor moves to top-left. */ |
s->cx = 0; |
screen_write_set_cursor(ctx, 0, 0); |
s->cy = 0; |
|
|
|
s->rupper = rupper; |
s->rupper = rupper; |
s->rlower = rlower; |
s->rlower = rlower; |
|
|
screen_write_collect_scroll(ctx); |
screen_write_collect_scroll(ctx); |
ctx->scrolled++; |
ctx->scrolled++; |
} else if (s->cy < screen_size_y(s) - 1) |
} else if (s->cy < screen_size_y(s) - 1) |
s->cy++; |
screen_write_set_cursor(ctx, -1, s->cy + 1); |
} |
} |
|
|
/* Scroll up. */ |
/* Scroll up. */ |
|
|
void |
void |
screen_write_carriagereturn(struct screen_write_ctx *ctx) |
screen_write_carriagereturn(struct screen_write_ctx *ctx) |
{ |
{ |
struct screen *s = ctx->s; |
screen_write_set_cursor(ctx, 0, -1); |
|
|
s->cx = 0; |
|
} |
} |
|
|
/* Clear to end of screen from cursor. */ |
/* Clear to end of screen from cursor. */ |
|
|
grid_view_set_cell(s->grid, xx, s->cy, |
grid_view_set_cell(s->grid, xx, s->cy, |
&grid_default_cell); |
&grid_default_cell); |
} |
} |
if (gc.data.width > 1) |
if (gc.data.width > 1) { |
grid_view_set_cell(s->grid, xx, s->cy, |
grid_view_set_cell(s->grid, xx, s->cy, |
&grid_default_cell); |
&grid_default_cell); |
|
} |
} |
} |
|
|
memcpy(&gc, &ci->gc, sizeof gc); |
memcpy(&gc, &ci->gc, sizeof gc); |
grid_view_set_cells(s->grid, s->cx, s->cy, &gc, ci->data, ci->used); |
grid_view_set_cells(s->grid, s->cx, s->cy, &gc, ci->data, ci->used); |
s->cx += ci->used; |
screen_write_set_cursor(ctx, s->cx + ci->used, -1); |
|
|
for (xx = s->cx; xx < screen_size_x(s); xx++) { |
for (xx = s->cx; xx < screen_size_x(s); xx++) { |
grid_view_get_cell(s->grid, xx, s->cy, &gc); |
grid_view_get_cell(s->grid, xx, s->cy, &gc); |
|
|
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy); |
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy); |
ci->wrapped = 1; |
ci->wrapped = 1; |
screen_write_linefeed(ctx, 1, 8); |
screen_write_linefeed(ctx, 1, 8); |
s->cx = 0; |
screen_write_set_cursor(ctx, 0, -1); |
} |
} |
|
|
if (ci->used == 0) |
if (ci->used == 0) |
|
|
if ((s->mode & MODE_WRAP) && s->cx > sx - width) { |
if ((s->mode & MODE_WRAP) && s->cx > sx - width) { |
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy); |
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy); |
screen_write_linefeed(ctx, 1, 8); |
screen_write_linefeed(ctx, 1, 8); |
s->cx = 0; |
screen_write_set_cursor(ctx, 0, -1); |
screen_write_collect_flush(ctx, 1); |
screen_write_collect_flush(ctx, 1); |
} |
} |
|
|
|
|
*/ |
*/ |
last = !(s->mode & MODE_WRAP); |
last = !(s->mode & MODE_WRAP); |
if (s->cx <= sx - last - width) |
if (s->cx <= sx - last - width) |
s->cx += width; |
screen_write_set_cursor(ctx, s->cx + width, -1); |
else |
else |
s->cx = sx - last; |
screen_write_set_cursor(ctx, sx - last, -1); |
|
|
/* Create space for character in insert mode. */ |
/* Create space for character in insert mode. */ |
if (s->mode & MODE_INSERT) { |
if (s->mode & MODE_INSERT) { |