mirror of
https://github.com/tmux/tmux.git
synced 2026-10-09 03:34:25 +00:00
Fix clear issue which lost C and A osc133 markers. Several cleanups.
This commit is contained in:
111
input.c
111
input.c
@@ -95,6 +95,14 @@ struct input_param {
|
||||
};
|
||||
};
|
||||
|
||||
/* Saved OSC 133 output marker. */
|
||||
struct input_osc_133_ctx {
|
||||
int running;
|
||||
u_int start;
|
||||
u_int col;
|
||||
u_int collected;
|
||||
};
|
||||
|
||||
/* Input parser context. */
|
||||
struct input_ctx {
|
||||
struct window_pane *wp;
|
||||
@@ -173,6 +181,9 @@ static void input_osc_110(struct input_ctx *, const char *);
|
||||
static void input_osc_111(struct input_ctx *, const char *);
|
||||
static void input_osc_112(struct input_ctx *, const char *);
|
||||
static void input_osc_133(struct input_ctx *, const char *);
|
||||
static struct input_osc_133_ctx input_osc_133_save_marker(struct input_ctx *);
|
||||
static void input_osc_133_restore_marker(struct input_ctx *,
|
||||
const struct input_osc_133_ctx *);
|
||||
|
||||
/* Transition entry/exit handlers. */
|
||||
static void input_clear(struct input_ctx *);
|
||||
@@ -1466,6 +1477,7 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
struct screen *s = sctx->s;
|
||||
const struct input_table_entry *entry;
|
||||
struct options *oo;
|
||||
struct input_osc_133_ctx osc133 = {0};
|
||||
int i, n, m, ek, set, p;
|
||||
u_int cx, bg = ictx->cell.cell.bg;
|
||||
|
||||
@@ -1739,13 +1751,19 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case -1:
|
||||
break;
|
||||
case 0:
|
||||
/* Erasing to the end clears the whole screen at 0,0. */
|
||||
if (s->cx == 0 && s->cy == 0)
|
||||
osc133 = input_osc_133_save_marker(ictx);
|
||||
screen_write_clearendofscreen(sctx, bg);
|
||||
input_osc_133_restore_marker(ictx, &osc133);
|
||||
break;
|
||||
case 1:
|
||||
screen_write_clearstartofscreen(sctx, bg);
|
||||
break;
|
||||
case 2:
|
||||
osc133 = input_osc_133_save_marker(ictx);
|
||||
screen_write_clearscreen(sctx, bg);
|
||||
input_osc_133_restore_marker(ictx, &osc133);
|
||||
break;
|
||||
case 3:
|
||||
if (input_get(ictx, 1, 0, 0) == 0) {
|
||||
@@ -3278,6 +3296,77 @@ input_osc_133_secondary_prompt(const char *p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Record the first primary or secondary prompt marker on a line. */
|
||||
static void
|
||||
input_osc_133_mark_prompt(struct grid_line *gl, u_int col, const char *p)
|
||||
{
|
||||
if (gl == NULL || gl->flags &
|
||||
(GRID_LINE_START_PROMPT|GRID_LINE_SECOND_PROMPT))
|
||||
return;
|
||||
gl->osc133_data.prompt_col = col;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
}
|
||||
|
||||
/* Save the running command's output start before clearing the screen. */
|
||||
static struct input_osc_133_ctx
|
||||
input_osc_133_save_marker(struct input_ctx *ictx)
|
||||
{
|
||||
struct window_pane *wp = ictx->wp;
|
||||
struct screen *s = ictx->ctx.s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_line *gl;
|
||||
struct input_osc_133_ctx ctx = {0};
|
||||
u_int y;
|
||||
|
||||
if (wp == NULL || s != &wp->base || SCREEN_IS_ALTERNATE(s) ||
|
||||
(~wp->flags & PANE_CMDRUNNING))
|
||||
return (ctx);
|
||||
ctx.running = 1;
|
||||
ctx.start = UINT_MAX;
|
||||
ctx.collected = gd->scroll_collected;
|
||||
for (y = gd->hsize + gd->sy; y > 0; y--) {
|
||||
gl = grid_get_line(gd, y - 1);
|
||||
if ((gl->flags & GRID_LINE_START_OUTPUT) &&
|
||||
(~gl->flags & GRID_LINE_END_OUTPUT ||
|
||||
gl->osc133_data.out_end_col < gl->osc133_data.out_start_col) &&
|
||||
(~gl->flags & GRID_LINE_START_PROMPT ||
|
||||
gl->osc133_data.prompt_col <= gl->osc133_data.out_start_col)) {
|
||||
ctx.start = y - 1;
|
||||
ctx.col = gl->osc133_data.out_start_col;
|
||||
break;
|
||||
}
|
||||
if (gl->flags & (GRID_LINE_START_PROMPT|GRID_LINE_END_OUTPUT))
|
||||
break;
|
||||
}
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/* Restore the running command's output start if a screen clear removed it. */
|
||||
static void
|
||||
input_osc_133_restore_marker(struct input_ctx *ictx,
|
||||
const struct input_osc_133_ctx *ctx)
|
||||
{
|
||||
struct grid *gd = ictx->ctx.s->grid;
|
||||
struct grid_line *gl;
|
||||
u_int collected;
|
||||
|
||||
if (!ctx->running)
|
||||
return;
|
||||
collected = gd->scroll_collected - ctx->collected;
|
||||
if (ctx->start != UINT_MAX && ctx->start >= collected) {
|
||||
gl = grid_get_line(gd, ctx->start - collected);
|
||||
if ((gl->flags & GRID_LINE_START_OUTPUT) &&
|
||||
gl->osc133_data.out_start_col == ctx->col)
|
||||
return;
|
||||
}
|
||||
gl = grid_get_line(gd, gd->hsize);
|
||||
gl->flags |= GRID_LINE_START_OUTPUT;
|
||||
gl->osc133_data.out_start_col = 0;
|
||||
}
|
||||
|
||||
/* Handle the OSC 133 sequence. */
|
||||
static void
|
||||
input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
@@ -3295,32 +3384,14 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
switch (*p) {
|
||||
case 'A':
|
||||
case 'N':
|
||||
if (gl != NULL) {
|
||||
if (!(gl->flags & (GRID_LINE_START_PROMPT|
|
||||
GRID_LINE_SECOND_PROMPT))) {
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
}
|
||||
}
|
||||
input_osc_133_mark_prompt(gl, s->cx, p);
|
||||
if (wp != NULL) {
|
||||
wp->last_prompt_time = time(NULL);
|
||||
events_fire_pane("pane-shell-prompt", wp);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (gl != NULL) {
|
||||
if (!(gl->flags & (GRID_LINE_START_PROMPT|
|
||||
GRID_LINE_SECOND_PROMPT))) {
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
}
|
||||
}
|
||||
input_osc_133_mark_prompt(gl, s->cx, p);
|
||||
break;
|
||||
case 'B':
|
||||
case 'I':
|
||||
|
||||
Reference in New Issue
Block a user