/* Set up context for TTY command. */ void screen_write_initctx( struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last) { struct screen *s = ctx->s; struct grid *gd = s->grid; const struct grid_cell *gc; const struct grid_utf8 *gu; u_int xx; ttyctx->wp = ctx->wp; ttyctx->ocx = s->cx; ttyctx->ocy = s->cy; ttyctx->orlower = s->rlower; ttyctx->orupper = s->rupper; if (!save_last) return; /* Save the last cell on the screen. */ gc = &grid_default_cell; for (xx = 1; xx <= screen_size_x(s); xx++) { gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy); if (!(gc->flags & GRID_FLAG_PADDING)) break; } ttyctx->last_width = xx; memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell); if (gc->flags & GRID_FLAG_UTF8) { gu = grid_view_peek_utf8(gd, screen_size_x(s) - xx, s->cy); memcpy(&ttyctx->last_utf8, gu, sizeof ttyctx->last_utf8); } }
/* * 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. */ void screen_write_overwrite(struct screen_write_ctx *ctx, u_int width) { struct screen *s = ctx->s; struct grid *gd = s->grid; const struct grid_cell *gc; u_int xx; gc = grid_view_peek_cell(gd, s->cx, s->cy); if (gc->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 + 1; while (--xx > 0) { gc = grid_view_peek_cell(gd, xx, s->cy); if (!(gc->flags & GRID_FLAG_PADDING)) break; grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); } /* Overwrite the character at the start of this padding. */ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); } /* * Overwrite any padding cells that belong to a UTF-8 character * we'll be overwriting with the current character. */ xx = s->cx + width - 1; while (++xx < screen_size_x(s)) { gc = grid_view_peek_cell(gd, xx, s->cy); if (!(gc->flags & GRID_FLAG_PADDING)) break; grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); } }
void tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) { const struct grid_cell *gc; const struct grid_utf8 *gu; u_int i, sx; sx = screen_size_x(s); if (sx > s->grid->size[s->grid->hsize + py]) sx = s->grid->size[s->grid->hsize + py]; if (sx > tty->sx) sx = tty->sx; tty_cursor(tty, 0, py, ox, oy); for (i = 0; i < sx; i++) { gc = grid_view_peek_cell(s->grid, i, py); gu = NULL; if (gc->flags & GRID_FLAG_UTF8) gu = grid_view_peek_utf8(s->grid, i, py); if (screen_check_selection(s, i, py)) { s->sel.cell.data = gc->data; tty_cell(tty, &s->sel.cell, gu); } else tty_cell(tty, gc, gu); } if (sx >= tty->sx) return; tty_reset(tty); tty_cursor(tty, sx, py, ox, oy); if (screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) tty_putcode(tty, TTYC_EL); else { for (i = sx; i < screen_size_x(s); i++) tty_putc(tty, ' '); } }
void tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) { const struct grid_cell *gc; struct grid_line *gl; struct grid_cell tmpgc; const struct grid_utf8 *gu; u_int i, sx; tty_update_mode(tty, tty->mode & ~MODE_CURSOR, s); sx = screen_size_x(s); if (sx > s->grid->linedata[s->grid->hsize + py].cellsize) sx = s->grid->linedata[s->grid->hsize + py].cellsize; if (sx > tty->sx) sx = tty->sx; /* * Don't move the cursor to the start permission if it will wrap there * itself. */ gl = NULL; if (py != 0) gl = &s->grid->linedata[s->grid->hsize + py - 1]; if (oy + py == 0 || gl == NULL || !(gl->flags & GRID_LINE_WRAPPED) || tty->cx < tty->sx || ox != 0 || (oy + py != tty->cy + 1 && tty->cy != s->rlower + oy)) tty_cursor(tty, ox, oy + py); for (i = 0; i < sx; i++) { gc = grid_view_peek_cell(s->grid, i, py); gu = NULL; if (gc->flags & GRID_FLAG_UTF8) gu = grid_view_peek_utf8(s->grid, i, py); if (screen_check_selection(s, i, py)) { memcpy(&tmpgc, &s->sel.cell, sizeof tmpgc); tmpgc.data = gc->data; tmpgc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmpgc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); tty_cell(tty, &tmpgc, gu); } else tty_cell(tty, gc, gu); } if (sx >= tty->sx) { tty_update_mode(tty, tty->mode, s); return; } tty_reset(tty); tty_cursor(tty, ox + sx, oy + py); if (screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) tty_putcode(tty, TTYC_EL); else { for (i = sx; i < screen_size_x(s); i++) tty_putc(tty, ' '); } tty_update_mode(tty, tty->mode, s); }