version 1.211, 2016/10/14 21:48:00 |
version 1.212, 2016/11/15 14:02:32 |
|
|
|
|
#include <netinet/in.h> |
#include <netinet/in.h> |
|
|
|
#include <curses.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <resolv.h> |
#include <resolv.h> |
|
|
|
|
static void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, |
static void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, |
u_int); |
u_int); |
|
static void tty_margin_pane(struct tty *, const struct tty_ctx *); |
static int tty_large_region(struct tty *, const struct tty_ctx *); |
static int tty_large_region(struct tty *, const struct tty_ctx *); |
static int tty_fake_bce(const struct tty *, const struct window_pane *, |
static int tty_fake_bce(const struct tty *, const struct window_pane *, |
u_int); |
u_int); |
|
|
|
|
#define tty_use_acs(tty) \ |
#define tty_use_acs(tty) \ |
(tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) |
(tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) |
|
#define tty_use_margin(tty) \ |
|
((tty)->term_type == TTY_VT420) |
|
|
#define tty_pane_full_width(tty, ctx) \ |
#define tty_pane_full_width(tty, ctx) \ |
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) |
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) |
|
|
tty->ccolour = xstrdup(""); |
tty->ccolour = xstrdup(""); |
|
|
tty->flags = 0; |
tty->flags = 0; |
|
|
tty->term_flags = 0; |
tty->term_flags = 0; |
|
tty->term_type = TTY_UNKNOWN; |
|
|
return (0); |
return (0); |
} |
} |
|
|
tty->cx = UINT_MAX; |
tty->cx = UINT_MAX; |
tty->cy = UINT_MAX; |
tty->cy = UINT_MAX; |
|
|
tty->rupper = UINT_MAX; |
tty->rupper = tty->rleft = UINT_MAX; |
tty->rlower = UINT_MAX; |
tty->rlower = tty->rright = UINT_MAX; |
|
|
/* |
/* |
* If the terminal has been started, reset the actual scroll region and |
* If the terminal has been started, reset the actual scroll region and |
|
|
if (tty->flags & TTY_STARTED) { |
if (tty->flags & TTY_STARTED) { |
tty_cursor(tty, 0, 0); |
tty_cursor(tty, 0, 0); |
tty_region(tty, 0, tty->sy - 1); |
tty_region(tty, 0, tty->sy - 1); |
|
tty_margin(tty, 0, tty->sx - 1); |
} |
} |
|
|
return (1); |
return (1); |
} |
} |
|
|
int |
int |
tty_set_size(struct tty *tty, u_int sx, u_int sy) { |
tty_set_size(struct tty *tty, u_int sx, u_int sy) |
|
{ |
if (sx == tty->sx && sy == tty->sy) |
if (sx == tty->sx && sy == tty->sy) |
return (0); |
return (0); |
tty->sx = sx; |
tty->sx = sx; |
|
|
tty->flags |= TTY_FOCUS; |
tty->flags |= TTY_FOCUS; |
tty_puts(tty, "\033[?1004h"); |
tty_puts(tty, "\033[?1004h"); |
} |
} |
|
tty_puts(tty, "\033[c"); |
} |
} |
|
|
tty->cx = UINT_MAX; |
tty->cx = UINT_MAX; |
tty->cy = UINT_MAX; |
tty->cy = UINT_MAX; |
|
|
tty->rlower = UINT_MAX; |
tty->rupper = tty->rleft = UINT_MAX; |
tty->rupper = UINT_MAX; |
tty->rlower = tty->rright = UINT_MAX; |
|
|
tty->mode = MODE_CURSOR; |
tty->mode = MODE_CURSOR; |
|
|
|
|
} |
} |
} |
} |
|
|
|
if (tty_use_margin(tty)) |
|
tty_raw(tty, "\033[?69l"); /* DECLRMM */ |
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); |
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); |
|
|
setblocking(tty->fd, 1); |
setblocking(tty->fd, 1); |
|
|
} |
} |
|
|
void |
void |
|
tty_set_type(struct tty *tty, int type) |
|
{ |
|
tty->term_type = type; |
|
|
|
if (tty_use_margin(tty)) |
|
tty_puts(tty, "\033[?69h"); /* DECLRMM */ |
|
} |
|
|
|
void |
tty_raw(struct tty *tty, const char *s) |
tty_raw(struct tty *tty, const char *s) |
{ |
{ |
ssize_t n, slen; |
ssize_t n, slen; |
|
|
tty_default_attributes(tty, ctx->wp, ctx->bg); |
tty_default_attributes(tty, ctx->wp, ctx->bg); |
|
|
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
|
|
tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ctx->num); |
tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ctx->num); |
|
|
tty_default_attributes(tty, ctx->wp, ctx->bg); |
tty_default_attributes(tty, ctx->wp, ctx->bg); |
|
|
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
|
|
tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ctx->num); |
tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ctx->num); |
|
|
tty_attributes(tty, &grid_default_cell, ctx->wp); |
tty_attributes(tty, &grid_default_cell, ctx->wp); |
|
|
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper); |
|
|
tty_putcode(tty, TTYC_RI); |
tty_putcode(tty, TTYC_RI); |
|
|
if (ctx->ocy != ctx->orlower) |
if (ctx->ocy != ctx->orlower) |
return; |
return; |
|
|
if (!tty_pane_full_width(tty, ctx) || |
if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) || |
tty_fake_bce(tty, wp, ctx->bg) || |
tty_fake_bce(tty, wp, ctx->bg) || |
!tty_term_has(tty->term, TTYC_CSR)) { |
!tty_term_has(tty->term, TTYC_CSR)) { |
if (tty_large_region(tty, ctx)) |
if (tty_large_region(tty, ctx)) |
|
|
} |
} |
|
|
/* |
/* |
* If this line wrapped naturally (ctx->num is nonzero), don't do |
* If this line wrapped naturally (ctx->num is nonzero) and we are not |
* anything - the cursor can just be moved to the last cell and wrap |
* using margins, don't do anything - the cursor can just be moved |
* naturally. |
* to the last cell and wrap naturally. |
*/ |
*/ |
if (ctx->num && !(tty->term->flags & TERM_EARLYWRAP)) |
if (!tty_use_margin(tty) && |
|
ctx->num != 0 && |
|
!(tty->term->flags & TERM_EARLYWRAP)) { |
return; |
return; |
|
} |
|
|
tty_attributes(tty, &grid_default_cell, wp); |
tty_attributes(tty, &grid_default_cell, wp); |
|
|
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
tty_margin_pane(tty, ctx); |
|
|
|
/* |
|
* If we want to wrap a pane, the cursor needs to be exactly on the |
|
* right of the region. But if the pane isn't on the right, it may be |
|
* off the edge - if so, move the cursor back to the right. |
|
*/ |
|
if (ctx->xoff + ctx->ocx > tty->rright) |
|
tty_cursor(tty, tty->rright, ctx->yoff + ctx->ocy); |
|
else |
|
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
|
|
tty_putc(tty, '\n'); |
tty_putc(tty, '\n'); |
} |
} |
|
|
|
|
tty_default_attributes(tty, wp, ctx->bg); |
tty_default_attributes(tty, wp, ctx->bg); |
|
|
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); |
|
|
if (tty_pane_full_width(tty, ctx) && |
if (tty_pane_full_width(tty, ctx) && |
|
|
tty_attributes(tty, &grid_default_cell, wp); |
tty_attributes(tty, &grid_default_cell, wp); |
|
|
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, 0, 0); |
tty_cursor_pane(tty, ctx, 0, 0); |
|
|
if (tty_pane_full_width(tty, ctx) && |
if (tty_pane_full_width(tty, ctx) && |
|
|
tty_default_attributes(tty, wp, ctx->bg); |
tty_default_attributes(tty, wp, ctx->bg); |
|
|
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
|
tty_margin_pane(tty, ctx); |
tty_cursor_pane(tty, ctx, 0, 0); |
tty_cursor_pane(tty, ctx, 0, 0); |
|
|
if (tty_pane_full_width(tty, ctx) && |
if (tty_pane_full_width(tty, ctx) && |
|
|
tty_attributes(tty, &grid_default_cell, wp); |
tty_attributes(tty, &grid_default_cell, wp); |
|
|
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); |
|
tty_margin_pane(tty, ctx); |
|
|
for (j = 0; j < screen_size_y(s); j++) { |
for (j = 0; j < screen_size_y(s); j++) { |
tty_cursor_pane(tty, ctx, 0, j); |
tty_cursor_pane(tty, ctx, 0, j); |
|
|
|
|
if (ctx->ocy == ctx->orlower) |
if (ctx->ocy == ctx->orlower) |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); |
|
tty_margin_pane(tty, ctx); |
|
|
/* Is the cursor in the very last position? */ |
/* Is the cursor in the very last position? */ |
width = ctx->cell->data.width; |
width = ctx->cell->data.width; |
|
|
tty_cursor(tty, 0, tty->cy); |
tty_cursor(tty, 0, tty->cy); |
|
|
tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower); |
tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower); |
|
tty_cursor(tty, 0, 0); |
|
} |
|
|
|
/* Set margin inside pane. */ |
|
static void |
|
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx) |
|
{ |
|
tty_margin(tty, ctx->xoff, ctx->xoff + ctx->wp->sx - 1); |
|
} |
|
|
|
/* Set margin at absolute position. */ |
|
void |
|
tty_margin(struct tty *tty, u_int rleft, u_int rright) |
|
{ |
|
char s[64]; |
|
|
|
if (!tty_use_margin(tty)) |
|
return; |
|
if (tty->rleft == rleft && tty->rright == rright) |
|
return; |
|
|
|
tty->rleft = rleft; |
|
tty->rright = rright; |
|
|
|
snprintf(s, sizeof s, "\033[%u;%us", rleft + 1, rright + 1); |
|
tty_puts(tty, s); |
tty_cursor(tty, 0, 0); |
tty_cursor(tty, 0, 0); |
} |
} |
|
|