void window_copy_scroll_down(struct window_pane *wp, u_int ny) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; if (ny > screen_hsize(&wp->base)) return; if (data->oy > screen_hsize(&wp->base) - ny) ny = screen_hsize(&wp->base) - data->oy; if (ny == 0) return; data->oy += ny; screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, ny); window_copy_write_lines(wp, &ctx, 0, ny); if (s->sel.flag && screen_size_y(s) > ny) { window_copy_update_selection(wp); window_copy_write_line(wp, &ctx, ny); } else if (ny == 1) /* nuke position */ window_copy_write_line(wp, &ctx, 1); screen_write_cursormove(&ctx, data->cx, data->cy); window_copy_update_selection(wp); screen_write_stop(&ctx); }
void window_copy_scroll_up(struct window_pane *wp, u_int ny) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; if (data->oy < ny) ny = data->oy; if (ny == 0) return; data->oy -= ny; screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, ny); window_copy_write_lines(wp, &ctx, screen_size_y(s) - ny, ny); window_copy_write_line(wp, &ctx, 0); if (screen_size_y(s) > 1) window_copy_write_line(wp, &ctx, 1); if (screen_size_y(s) > 3) window_copy_write_line(wp, &ctx, screen_size_y(s) - 2); if (s->sel.flag && screen_size_y(s) > ny) { window_copy_update_selection(wp); window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1); } screen_write_cursormove(&ctx, data->cx, data->cy); window_copy_update_selection(wp); screen_write_stop(&ctx); }
void window_copy_write_line( struct window_pane *wp, struct screen_write_ctx *ctx, u_int py) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct options *oo = &wp->window->options; struct grid_cell gc; char hdr[32]; size_t last, xoff = 0, size = 0; memcpy(&gc, &grid_default_cell, sizeof gc); colour_set_fg(&gc, options_get_number(oo, "mode-fg")); colour_set_bg(&gc, options_get_number(oo, "mode-bg")); gc.attr |= options_get_number(oo, "mode-attr"); last = screen_size_y(s) - 1; if (py == 0) { size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->oy, screen_hsize(data->backing)); if (size > screen_size_x(s)) size = screen_size_x(s); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); } else if (py == last && data->inputtype != WINDOW_COPY_OFF) { if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) { xoff = size = xsnprintf(hdr, sizeof hdr, "Repeat: %u", data->numprefix); } else { xoff = size = xsnprintf(hdr, sizeof hdr, "%s: %s", data->inputprompt, data->inputstr); } screen_write_cursormove(ctx, 0, last); screen_write_puts(ctx, &gc, "%s", hdr); } else size = 0; screen_write_cursormove(ctx, xoff, py); screen_write_copy(ctx, data->backing, xoff, (screen_hsize(data->backing) - data->oy) + py, screen_size_x(s) - size, 1); if (py == data->cy && data->cx == screen_size_x(s)) { memcpy(&gc, &grid_default_cell, sizeof gc); screen_write_cursormove(ctx, screen_size_x(s) - 1, py); screen_write_putc(ctx, &gc, '$'); } }
/* Handle CSI private SM. */ void input_csi_dispatch_sm_private(struct input_ctx *ictx) { u_int i; for (i = 0; i < ictx->param_list_len; i++) { switch (input_get(ictx, i, 0, -1)) { case 1: /* DECCKM */ screen_write_mode_set(&ictx->ctx, MODE_KCURSOR); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 7: /* DECAWM */ screen_write_mode_set(&ictx->ctx, MODE_WRAP); break; case 25: /* TCEM */ screen_write_mode_set(&ictx->ctx, MODE_CURSOR); break; case 1000: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD); break; case 1002: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON); break; case 1003: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY); break; case 1004: if (ictx->ctx.s->mode & MODE_FOCUSON) break; screen_write_mode_set(&ictx->ctx, MODE_FOCUSON); ictx->wp->flags |= PANE_FOCUSPUSH; /* force update */ break; case 1005: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8); break; case 1006: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR); break; case 47: case 1047: window_pane_alternate_on(ictx->wp, &ictx->cell, 0); break; case 1049: window_pane_alternate_on(ictx->wp, &ictx->cell, 1); break; case 2004: screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } } }
/* Copy from another screen. */ void 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; struct grid *gd = src->grid; struct grid_line *gl; const struct grid_cell *gc; const struct grid_utf8 *gu; struct utf8_data utf8data; u_int xx, yy, cx, cy, ax, bx; cx = s->cx; cy = s->cy; for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; if (yy < gd->hsize + gd->sy) { /* * Find start and end position and copy between * them. Limit to the real end of the line then use a * clear EOL only if copying to the end, otherwise * could overwrite whatever is there already. */ if (px > gl->cellsize) ax = gl->cellsize; else ax = px; if (px + nx == gd->sx && px + nx > gl->cellsize) bx = gl->cellsize; else bx = px + nx; for (xx = ax; xx < bx; xx++) { if (xx >= gl->cellsize) gc = &grid_default_cell; else gc = &gl->celldata[xx]; if (!(gc->flags & GRID_FLAG_UTF8)) { screen_write_cell(ctx, gc, NULL); continue; } /* Reinject the UTF-8 sequence. */ gu = &gl->utf8data[xx]; utf8data.size = grid_utf8_copy( gu, utf8data.data, sizeof utf8data.data); utf8data.width = gu->width; screen_write_cell(ctx, gc, &utf8data); } if (px + nx == gd->sx && px + nx > gl->cellsize) screen_write_clearendofline(ctx); } else screen_write_clearline(ctx); cy++; screen_write_cursormove(ctx, cx, cy); } }
/* Handle CSI private RM. */ void input_csi_dispatch_rm_private(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; u_int i; for (i = 0; i < ictx->param_list_len; i++) { switch (input_get(ictx, i, 0, -1)) { case 1: /* DECCKM */ screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 7: /* DECAWM */ screen_write_mode_clear(&ictx->ctx, MODE_WRAP); break; case 12: screen_write_mode_clear(&ictx->ctx, MODE_BLINKING); break; case 25: /* TCEM */ screen_write_mode_clear(&ictx->ctx, MODE_CURSOR); break; case 1000: case 1001: case 1002: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); break; case 1004: screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON); break; case 1005: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8); break; case 1006: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR); break; case 47: case 1047: window_pane_alternate_off(wp, &ictx->cell.cell, 0); break; case 1049: window_pane_alternate_off(wp, &ictx->cell.cell, 1); break; case 2004: screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } } }
struct screen * window_copy_init(struct window_pane *wp) { struct window_copy_mode_data *data; struct screen *s; struct screen_write_ctx ctx; u_int i; int keys; wp->modedata = data = xmalloc(sizeof *data); data->oy = 0; data->cx = wp->base.cx; data->cy = wp->base.cy; data->lastcx = 0; data->lastsx = 0; data->rectflag = 0; data->inputtype = WINDOW_COPY_OFF; data->inputprompt = NULL; data->inputstr = xstrdup(""); data->numprefix = 0; data->searchtype = WINDOW_COPY_OFF; data->searchstr = NULL; wp->flags |= PANE_FREEZE; bufferevent_disable(wp->event, EV_READ|EV_WRITE); s = &data->screen; screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); if (options_get_number(&wp->window->options, "mode-mouse")) s->mode |= MODE_MOUSE; keys = options_get_number(&wp->window->options, "mode-keys"); if (keys == MODEKEY_EMACS) mode_key_init(&data->mdata, &mode_key_tree_emacs_copy); else mode_key_init(&data->mdata, &mode_key_tree_vi_copy); s->cx = data->cx; s->cy = data->cy; screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) window_copy_write_line(wp, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); return (s); }
void window_copy_redraw_lines(struct window_pane *wp, u_int py, u_int ny) { struct window_copy_mode_data *data = wp->modedata; struct screen_write_ctx ctx; u_int i; screen_write_start(&ctx, wp, NULL); for (i = py; i < py + ny; i++) window_copy_write_line(wp, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); }
/* Reset screen state. */ void screen_write_reset(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; screen_reset_tabs(s); screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1); s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD|MODE_FOCUSON); s->mode &= ~(ALL_MOUSE_MODES|MODE_MOUSE_UTF8|MODE_MOUSE_SGR); screen_write_clearscreen(ctx, 8); screen_write_cursormove(ctx, 0, 0); }
void window_more_write_line( struct window_pane *wp, struct screen_write_ctx *ctx, u_int py) { struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct options *oo = &wp->window->options; struct grid_cell gc; char *msg, hdr[32]; size_t size; int utf8flag; utf8flag = options_get_number(&wp->window->options, "utf8"); memcpy(&gc, &grid_default_cell, sizeof gc); if (py == 0) { size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); colour_set_fg(&gc, options_get_number(oo, "mode-fg")); colour_set_bg(&gc, options_get_number(oo, "mode-bg")); gc.attr |= options_get_number(oo, "mode-attr"); screen_write_puts(ctx, &gc, "%s", hdr); memcpy(&gc, &grid_default_cell, sizeof gc); } else size = 0; screen_write_cursormove(ctx, 0, py); if (data->top + py < ARRAY_LENGTH(&data->list)) { msg = ARRAY_ITEM(&data->list, data->top + py); screen_write_nputs( ctx, screen_size_x(s) - size, &gc, utf8flag, "%s", msg); } while (s->cx < screen_size_x(s) - size) screen_write_putc(ctx, &gc, ' '); }
/* Reset screen state. */ void screen_write_reset(struct screen_write_ctx *ctx) { screen_reset_tabs(ctx->s); screen_write_scrollregion(ctx, 0, screen_size_y(ctx->s) - 1); screen_write_insertmode(ctx, 0); screen_write_kcursormode(ctx, 0); screen_write_kkeypadmode(ctx, 0); screen_write_mousemode_off(ctx); screen_write_clearscreen(ctx); screen_write_cursormove(ctx, 0, 0); }
/* Copy from another screen. */ void 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; struct grid *gd = src->grid; struct grid_line *gl; const struct grid_cell *gc; struct utf8_data ud; u_int xx, yy, cx, cy, ax, bx; cx = s->cx; cy = s->cy; for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; if (yy < gd->hsize + gd->sy) { /* * Find start and end position and copy between * them. Limit to the real end of the line then use a * clear EOL only if copying to the end, otherwise * could overwrite whatever is there already. */ if (px > gl->cellsize) ax = gl->cellsize; else ax = px; if (px + nx == gd->sx && px + nx > gl->cellsize) bx = gl->cellsize; else bx = px + nx; for (xx = ax; xx < bx; xx++) { if (xx >= gl->cellsize) gc = &grid_default_cell; else gc = &gl->celldata[xx]; grid_cell_get(gc, &ud); screen_write_cell(ctx, gc); } if (px + nx == gd->sx && px + nx > gl->cellsize) screen_write_clearendofline(ctx); } else screen_write_clearline(ctx); cy++; screen_write_cursormove(ctx, cx, cy); } }
void window_more_scroll_up(struct window_pane *wp) { struct window_more_mode_data *data = wp->modedata; struct screen_write_ctx ctx; if (data->top == 0) return; data->top--; screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, 1); window_more_write_line(wp, &ctx, 0); window_more_write_line(wp, &ctx, 1); screen_write_stop(&ctx); }
void window_more_scroll_down(struct window_pane *wp) { struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; if (data->top >= ARRAY_LENGTH(&data->list)) return; data->top++; screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, 1); window_more_write_line(wp, &ctx, screen_size_y(s) - 1); window_more_write_line(wp, &ctx, 0); screen_write_stop(&ctx); }
/* Flush outstanding cell writes. */ static void screen_write_flush(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; struct tty_ctx ttyctx; u_int x, y, offset, cx, cy, dirty; struct grid_cell gc; if (ctx->dirty == 0) return; dirty = 0; log_debug("%s: dirty %u", __func__, ctx->dirty); cx = s->cx; cy = s->cy; offset = 0; for (y = 0; y < screen_size_y(s); y++) { for (x = 0; x < screen_size_x(s); x++) { offset++; if (!bit_test(s->dirty, offset - 1)) continue; bit_clear(s->dirty, offset - 1); screen_write_cursormove(ctx, x, y); grid_view_get_cell(s->grid, x, y, &gc); screen_write_initctx(ctx, &ttyctx); ttyctx.cell = &gc; tty_write(tty_cmd_cell, &ttyctx); ctx->written++; if (++dirty == ctx->dirty) break; } if (dirty == ctx->dirty) break; } ctx->dirty = 0; s->cx = cx; s->cy = cy; }
void window_copy_update_cursor(struct window_pane *wp, u_int cx, u_int cy) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int old_cx, old_cy; old_cx = data->cx; old_cy = data->cy; data->cx = cx; data->cy = cy; if (old_cx == screen_size_x(s)) window_copy_redraw_lines(wp, old_cy, 1); if (data->cx == screen_size_x(s)) window_copy_redraw_lines(wp, data->cy, 1); else { screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } }
/* Copy from another screen. */ void 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; struct grid *gd = src->grid; 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++) { grid_get_cell(gd, xx, yy, &gc); screen_write_cell(ctx, &gc); } cy++; screen_write_cursormove(ctx, cx, cy); } }
static void window_buffer_draw(__unused void *modedata, void *itemdata, struct screen_write_ctx *ctx, u_int sx, u_int sy) { struct window_buffer_itemdata *item = itemdata; struct paste_buffer *pb; char line[1024]; const char *pdata, *end, *cp; size_t psize, at; u_int i, cx = ctx->s->cx, cy = ctx->s->cy; pb = paste_get_name(item->name); if (pb == NULL) return; pdata = end = paste_buffer_data(pb, &psize); for (i = 0; i < sy; i++) { at = 0; while (end != pdata + psize && *end != '\n') { if ((sizeof line) - at > 5) { cp = vis(line + at, *end, VIS_TAB|VIS_OCTAL, 0); at = cp - line; } end++; } if (at > sx) at = sx; line[at] = '\0'; if (*line != '\0') { screen_write_cursormove(ctx, cx, cy + i, 0); screen_write_puts(ctx, &grid_default_cell, "%s", line); } if (end == pdata + psize) break; end++; } }
void window_copy_init_from_pane(struct window_pane *wp) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; if (wp->mode != &window_copy_mode) fatalx("not in copy mode"); data->backing = &wp->base; data->cx = data->backing->cx; data->cy = data->backing->cy; s->cx = data->cx; s->cy = data->cy; screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) window_copy_write_line(wp, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); }
/* Execute escape sequence. */ int input_esc_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; struct screen *s = sctx->s; struct input_table_entry *entry; if (ictx->flags & INPUT_DISCARD) return (0); log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf); entry = bsearch(ictx, input_esc_table, nitems(input_esc_table), sizeof input_esc_table[0], input_table_compare); if (entry == NULL) { log_debug("%s: unknown '%c'", __func__, ictx->ch); return (0); } switch (entry->type) { case INPUT_ESC_RIS: input_reset_cell(ictx); screen_write_reset(sctx); break; case INPUT_ESC_IND: screen_write_linefeed(sctx, 0); break; case INPUT_ESC_NEL: screen_write_carriagereturn(sctx); screen_write_linefeed(sctx, 0); break; case INPUT_ESC_HTS: if (s->cx < screen_size_x(s)) bit_set(s->tabs, s->cx); break; case INPUT_ESC_RI: screen_write_reverseindex(sctx); break; case INPUT_ESC_DECKPAM: screen_write_mode_set(sctx, MODE_KKEYPAD); break; case INPUT_ESC_DECKPNM: screen_write_mode_clear(sctx, MODE_KKEYPAD); break; case INPUT_ESC_DECSC: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); ictx->old_cx = s->cx; ictx->old_cy = s->cy; break; case INPUT_ESC_DECRC: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); break; case INPUT_ESC_DECALN: screen_write_alignmenttest(sctx); break; case INPUT_ESC_SCSG0_ON: ictx->cell.g0set = 1; break; case INPUT_ESC_SCSG0_OFF: ictx->cell.g0set = 0; break; case INPUT_ESC_SCSG1_ON: ictx->cell.g1set = 1; break; case INPUT_ESC_SCSG1_OFF: ictx->cell.g1set = 0; break; } return (0); }
/* Execute control sequence. */ int input_csi_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; struct screen *s = sctx->s; struct input_table_entry *entry; int n, m; if (ictx->flags & INPUT_DISCARD) return (0); if (input_split(ictx) != 0) return (0); log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch, ictx->interm_buf, ictx->param_buf); entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), sizeof input_csi_table[0], input_table_compare); if (entry == NULL) { log_debug("%s: unknown '%c'", __func__, ictx->ch); return (0); } switch (entry->type) { case INPUT_CSI_CBT: /* Find the previous tab point, n times. */ n = input_get(ictx, 0, 1, 1); while (s->cx > 0 && n-- > 0) { do s->cx--; while (s->cx > 0 && !bit_test(s->tabs, s->cx)); } break; case INPUT_CSI_CUB: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUD: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUF: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUP: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, 1); screen_write_cursormove(sctx, m - 1, n - 1); break; case INPUT_CSI_CUU: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CNL: screen_write_carriagereturn(sctx); screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CPL: screen_write_carriagereturn(sctx); screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DA: switch (input_get(ictx, 0, 0, 0)) { case 0: input_reply(ictx, "\033[?1;2c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_DA_TWO: switch (input_get(ictx, 0, 0, 0)) { case 0: input_reply(ictx, "\033[>0;95;0c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_ECH: screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DCH: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DECSTBM: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, screen_size_y(s)); screen_write_scrollregion(sctx, n - 1, m - 1); break; case INPUT_CSI_DL: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DSR: switch (input_get(ictx, 0, 0, 0)) { case 5: input_reply(ictx, "\033[0n"); break; case 6: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_ED: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofscreen(sctx); break; case 1: screen_write_clearstartofscreen(sctx); break; case 2: screen_write_clearscreen(sctx); break; case 3: switch (input_get(ictx, 1, 0, 0)) { case 0: /* * Linux console extension to clear history * (for example before locking the screen). */ screen_write_clearhistory(sctx); break; } break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_EL: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofline(sctx); break; case 1: screen_write_clearstartofline(sctx); break; case 2: screen_write_clearline(sctx); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_HPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, n - 1, s->cy); break; case INPUT_CSI_ICH: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_IL: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_RCP: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); break; case INPUT_CSI_RM: input_csi_dispatch_rm(ictx); break; case INPUT_CSI_RM_PRIVATE: input_csi_dispatch_rm_private(ictx); break; case INPUT_CSI_SCP: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); ictx->old_cx = s->cx; ictx->old_cy = s->cy; break; case INPUT_CSI_SGR: input_csi_dispatch_sgr(ictx); break; case INPUT_CSI_SM: input_csi_dispatch_sm(ictx); break; case INPUT_CSI_SM_PRIVATE: input_csi_dispatch_sm_private(ictx); break; case INPUT_CSI_TBC: switch (input_get(ictx, 0, 0, 0)) { case 0: if (s->cx < screen_size_x(s)) bit_clear(s->tabs, s->cx); break; case 3: bit_nclear(s->tabs, 0, screen_size_x(s) - 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_VPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, s->cx, n - 1); break; case INPUT_CSI_DECSCUSR: n = input_get(ictx, 0, 0, 0); screen_set_cursor_style(s, n); break; } return (0); }
/* Execute control sequence. */ int input_csi_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; struct window_pane *wp = ictx->wp; struct screen *s = sctx->s; struct input_table_entry *entry; int n, m; if (ictx->flags & INPUT_DISCARD) return (0); if (input_split(ictx) != 0) return (0); log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch, ictx->interm_buf, ictx->param_buf); entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), sizeof input_csi_table[0], input_table_compare); if (entry == NULL) { log_debug("%s: unknown '%c'", __func__, ictx->ch); return (0); } switch (entry->type) { case INPUT_CSI_CBT: /* Find the previous tab point, n times. */ n = input_get(ictx, 0, 1, 1); while (s->cx > 0 && n-- > 0) { do s->cx--; while (s->cx > 0 && !bit_test(s->tabs, s->cx)); } break; case INPUT_CSI_CUB: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUD: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUF: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUP: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, 1); screen_write_cursormove(sctx, m - 1, n - 1); break; case INPUT_CSI_CUU: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DA: switch (input_get(ictx, 0, 0, 0)) { case 0: input_reply(ictx, "\033[?1;2c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_DCH: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DECSTBM: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, screen_size_y(s)); screen_write_scrollregion(sctx, n - 1, m - 1); break; case INPUT_CSI_DL: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DSR: switch (input_get(ictx, 0, 0, 0)) { case 5: input_reply(ictx, "\033[0n"); break; case 6: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_ED: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofscreen(sctx); break; case 1: screen_write_clearstartofscreen(sctx); break; case 2: screen_write_clearscreen(sctx); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_EL: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofline(sctx); break; case 1: screen_write_clearstartofline(sctx); break; case 2: screen_write_clearline(sctx); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_HPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, n - 1, s->cy); break; case INPUT_CSI_ICH: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_IL: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_RM: switch (input_get(ictx, 0, 0, -1)) { case 4: /* IRM */ screen_write_insertmode(&ictx->ctx, 0); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_RM_PRIVATE: switch (input_get(ictx, 0, 0, -1)) { case 1: /* GATM */ screen_write_kcursormode(&ictx->ctx, 0); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 25: /* TCEM */ screen_write_cursormode(&ictx->ctx, 0); break; case 1000: screen_write_mousemode(&ictx->ctx, 0); break; case 1049: window_pane_alternate_off(wp, &ictx->cell); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_SGR: input_csi_dispatch_sgr(ictx); break; case INPUT_CSI_SM: switch (input_get(ictx, 0, 0, -1)) { case 4: /* IRM */ screen_write_insertmode(&ictx->ctx, 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_SM_PRIVATE: switch (input_get(ictx, 0, 0, -1)) { case 1: /* GATM */ screen_write_kcursormode(&ictx->ctx, 1); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 25: /* TCEM */ screen_write_cursormode(&ictx->ctx, 1); break; case 1000: screen_write_mousemode(&ictx->ctx, 1); break; case 1049: window_pane_alternate_on(wp, &ictx->cell); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_TBC: switch (input_get(ictx, 0, 0, 0)) { case 0: if (s->cx < screen_size_x(s)) bit_clear(s->tabs, s->cx); break; case 3: bit_nclear(s->tabs, 0, screen_size_x(s) - 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_VPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, s->cx, n - 1); break; } return (0); }
void window_clock_draw_screen(struct window_pane *wp) { struct window_clock_mode_data *data = wp->modedata; struct screen_write_ctx ctx; int colour, style; struct screen *s = &data->screen; struct grid_cell gc; char tim[64], *ptr; time_t t; struct tm *tm; u_int i, j, x, y, idx; colour = options_get_number(&wp->window->options, "clock-mode-colour"); style = options_get_number(&wp->window->options, "clock-mode-style"); screen_write_start(&ctx, NULL, s); t = time(NULL); tm = localtime(&t); if (style == 0) { strftime(tim, sizeof tim, "%l:%M ", localtime(&t)); if (tm->tm_hour >= 12) strlcat(tim, "PM", sizeof tim); else strlcat(tim, "AM", sizeof tim); } else strftime(tim, sizeof tim, "%H:%M", tm); screen_write_clearscreen(&ctx); if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { x = (screen_size_x(s) / 2) - (strlen(tim) / 2); y = screen_size_y(s) / 2; screen_write_cursormove(&ctx, x, y); memcpy(&gc, &grid_default_cell, sizeof gc); colour_set_fg(&gc, colour); screen_write_puts(&ctx, &gc, "%s", tim); } screen_write_stop(&ctx); return; } x = (screen_size_x(s) / 2) - 3 * strlen(tim); y = (screen_size_y(s) / 2) - 3; memcpy(&gc, &grid_default_cell, sizeof gc); colour_set_bg(&gc, colour); for (ptr = tim; *ptr != '\0'; ptr++) { if (*ptr >= '0' && *ptr <= '9') idx = *ptr - '0'; else if (*ptr == ':') idx = 10; else if (*ptr == 'A') idx = 11; else if (*ptr == 'P') idx = 12; else if (*ptr == 'M') idx = 13; else { x += 6; continue; } for (j = 0; j < 5; j++) { for (i = 0; i < 5; i++) { screen_write_cursormove(&ctx, x + i, y + j); if (window_clock_table[idx][j][i]) screen_write_putc(&ctx, &gc, ' '); } } x += 6; } screen_write_stop(&ctx); }
void clock_draw(struct screen_write_ctx *ctx, u_int colour, int style) { struct screen *s = ctx->s; struct grid_cell gc; char tim[64], *ptr; time_t t; u_int i, j, x, y, idx; t = time(NULL); if (style == 0) strftime(tim, sizeof tim, "%l:%M %p", localtime(&t)); else strftime(tim, sizeof tim, "%H:%M", localtime(&t)); screen_write_clearscreen(ctx); memcpy(&gc, &grid_default_cell, sizeof gc); gc.fg = colour; if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { x = (screen_size_x(s) / 2) - (strlen(tim) / 2); y = screen_size_y(s) / 2; screen_write_cursormove(ctx, x, y); gc.fg = colour; screen_write_puts(ctx, &gc, "%s", tim); } return; } x = (screen_size_x(s) / 2) - 3 * strlen(tim); y = (screen_size_y(s) / 2) - 3; for (ptr = tim; *ptr != '\0'; ptr++) { if (*ptr >= '0' && *ptr <= '9') idx = *ptr - '0'; else if (*ptr == ':') idx = 10; else if (*ptr == 'A') idx = 11; else if (*ptr == 'P') idx = 12; else if (*ptr == 'M') idx = 13; else { x += 6; continue; } for (j = 0; j < 5; j++) { screen_write_cursormove(ctx, x, y + j); for (i = 0; i < 5; i++) { if (clock_table[idx][j][i]) gc.attr |= GRID_ATTR_REVERSE; else gc.attr &= ~GRID_ATTR_REVERSE; screen_write_putc(ctx, &gc, ' '); } } x += 6; } }
/* Execute escape sequence. */ int input_esc_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; struct screen *s = sctx->s; struct input_table_entry *entry; if (ictx->flags & INPUT_DISCARD) return (0); log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf); entry = bsearch(ictx, input_esc_table, nitems(input_esc_table), sizeof input_esc_table[0], input_table_compare); if (entry == NULL) { log_debug("%s: unknown '%c'", __func__, ictx->ch); return (0); } switch (entry->type) { case INPUT_ESC_RIS: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell); memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); ictx->old_cx = 0; ictx->old_cy = 0; screen_write_reset(sctx); break; case INPUT_ESC_IND: screen_write_linefeed(sctx, 0); break; case INPUT_ESC_NEL: screen_write_carriagereturn(sctx); screen_write_linefeed(sctx, 0); break; case INPUT_ESC_HTS: if (s->cx < screen_size_x(s)) bit_set(s->tabs, s->cx); break; case INPUT_ESC_RI: screen_write_reverseindex(sctx); break; case INPUT_ESC_DECKPAM: screen_write_mode_set(sctx, MODE_KKEYPAD); break; case INPUT_ESC_DECKPNM: screen_write_mode_clear(sctx, MODE_KKEYPAD); break; case INPUT_ESC_DECSC: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); ictx->old_cx = s->cx; ictx->old_cy = s->cy; break; case INPUT_ESC_DECRC: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); break; case INPUT_ESC_DECALN: screen_write_alignmenttest(sctx); break; case INPUT_ESC_SCSON_G0: /* * Not really supported, but fake it up enough for those that * use it to switch character sets (by redefining G0 to * graphics set, rather than switching to G1). */ ictx->cell.attr &= ~GRID_ATTR_CHARSET; break; case INPUT_ESC_SCSOFF_G0: ictx->cell.attr |= GRID_ATTR_CHARSET; break; } return (0); }
/* Execute control sequence. */ int input_csi_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; struct window_pane *wp = ictx->wp; struct screen *s = sctx->s; struct input_table_entry *entry; int n, m; if (ictx->flags & INPUT_DISCARD) return (0); if (input_split(ictx) != 0) return (0); log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch, ictx->interm_buf, ictx->param_buf); entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), sizeof input_csi_table[0], input_table_compare); if (entry == NULL) { log_debug("%s: unknown '%c'", __func__, ictx->ch); return (0); } switch (entry->type) { case INPUT_CSI_CBT: /* Find the previous tab point, n times. */ n = input_get(ictx, 0, 1, 1); while (s->cx > 0 && n-- > 0) { do s->cx--; while (s->cx > 0 && !bit_test(s->tabs, s->cx)); } break; case INPUT_CSI_CUB: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUD: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUF: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CUP: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, 1); screen_write_cursormove(sctx, m - 1, n - 1); break; case INPUT_CSI_CUU: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CNL: screen_write_carriagereturn(sctx); screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_CPL: screen_write_carriagereturn(sctx); screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DA: switch (input_get(ictx, 0, 0, 0)) { case 0: input_reply(ictx, "\033[?1;2c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_DA_TWO: switch (input_get(ictx, 0, 0, 0)) { case 0: input_reply(ictx, "\033[>0;95;0c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_ECH: screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DCH: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DECSTBM: n = input_get(ictx, 0, 1, 1); m = input_get(ictx, 1, 1, screen_size_y(s)); screen_write_scrollregion(sctx, n - 1, m - 1); break; case INPUT_CSI_DL: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_DSR: switch (input_get(ictx, 0, 0, 0)) { case 5: input_reply(ictx, "\033[0n"); break; case 6: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_ED: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofscreen(sctx); break; case 1: screen_write_clearstartofscreen(sctx); break; case 2: screen_write_clearscreen(sctx); break; case 3: switch (input_get(ictx, 1, 0, 0)) { case 0: /* * Linux console extension to clear history * (for example before locking the screen). */ screen_write_clearhistory(sctx); break; } break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_EL: switch (input_get(ictx, 0, 0, 0)) { case 0: screen_write_clearendofline(sctx); break; case 1: screen_write_clearstartofline(sctx); break; case 2: screen_write_clearline(sctx); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_HPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, n - 1, s->cy); break; case INPUT_CSI_ICH: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_IL: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1)); break; case INPUT_CSI_RCP: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); break; case INPUT_CSI_RM: switch (input_get(ictx, 0, 0, -1)) { case 4: /* IRM */ screen_write_mode_clear(&ictx->ctx, MODE_INSERT); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_RM_PRIVATE: switch (input_get(ictx, 0, 0, -1)) { case 1: /* GATM */ screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 7: /* DECAWM */ screen_write_mode_clear(&ictx->ctx, MODE_WRAP); break; case 25: /* TCEM */ screen_write_mode_clear(&ictx->ctx, MODE_CURSOR); break; case 1000: case 1001: case 1002: case 1003: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); break; case 1004: wp->focus_notify &= ~PANE_FOCUS_NOTIFY; break; case 1005: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8); break; case 1006: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR); break; case 47: case 1047: window_pane_alternate_off(wp, &ictx->cell, 0); break; case 1049: window_pane_alternate_off(wp, &ictx->cell, 1); break; case 2004: screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_SCP: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); ictx->old_cx = s->cx; ictx->old_cy = s->cy; break; case INPUT_CSI_SGR: input_csi_dispatch_sgr(ictx); break; case INPUT_CSI_SM: switch (input_get(ictx, 0, 0, -1)) { case 4: /* IRM */ screen_write_mode_set(&ictx->ctx, MODE_INSERT); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_SM_PRIVATE: switch (input_get(ictx, 0, 0, -1)) { case 1: /* GATM */ screen_write_mode_set(&ictx->ctx, MODE_KCURSOR); break; case 3: /* DECCOLM */ screen_write_cursormove(&ictx->ctx, 0, 0); screen_write_clearscreen(&ictx->ctx); break; case 7: /* DECAWM */ screen_write_mode_set(&ictx->ctx, MODE_WRAP); break; case 25: /* TCEM */ screen_write_mode_set(&ictx->ctx, MODE_CURSOR); break; case 1000: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD); break; case 1002: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON); break; case 1003: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY); break; case 1004: wp->focus_notify |= PANE_FOCUS_NOTIFY; break; case 1005: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8); break; case 1006: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR); break; case 47: case 1047: window_pane_alternate_on(wp, &ictx->cell, 0); break; case 1049: window_pane_alternate_on(wp, &ictx->cell, 1); break; case 2004: screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_TBC: switch (input_get(ictx, 0, 0, 0)) { case 0: if (s->cx < screen_size_x(s)) bit_clear(s->tabs, s->cx); break; case 3: bit_nclear(s->tabs, 0, screen_size_x(s) - 1); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); break; } break; case INPUT_CSI_VPA: n = input_get(ictx, 0, 1, 1); screen_write_cursormove(sctx, s->cx, n - 1); break; case INPUT_CSI_DECSCUSR: n = input_get(ictx, 0, 0, 0); screen_set_cursor_style(s, n); break; } return (0); }