summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2024-10-28 08:12:00 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2024-10-28 08:12:00 +0000
commit67c94f1f14de42a74d4b24d1e3c99b065709f455 (patch)
tree536295605757b0e15894877b369f547d282cb38f /usr.bin/tmux
parent858234e1518ff2609d1ea1f2a7450af90214ae0e (diff)
Fix issues in the command prompt: set PROMPT_QUOTENEXT after quoting
than before, meaning that accidentally scrolling the mouse wheel doesn't break quoting; and move the cursor correctly over wide characters. From Alexander Arch in GitHub issue 4212.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/status.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c
index 6e3a68ed17b..942eeba278c 100644
--- a/usr.bin/tmux/status.c
+++ b/usr.bin/tmux/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.249 2024/10/25 15:32:51 nicm Exp $ */
+/* $OpenBSD: status.c,v 1.250 2024/10/28 08:11:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -728,6 +728,55 @@ status_prompt_update(struct client *c, const char *msg, const char *input)
format_free(ft);
}
+/* Redraw character. Return 1 if can continue redrawing, 0 otherwise. */
+static int
+status_prompt_redraw_character(struct screen_write_ctx *ctx, u_int offset,
+ u_int pwidth, u_int *width, struct grid_cell *gc,
+ const struct utf8_data *ud)
+{
+ u_char ch;
+
+ if (*width < offset) {
+ *width += ud->width;
+ return (1);
+ }
+ if (*width >= offset + pwidth)
+ return (0);
+ *width += ud->width;
+ if (*width > offset + pwidth)
+ return (0);
+
+ ch = *ud->data;
+ if (ud->size == 1 && (ch <= 0x1f || ch == 0x7f)) {
+ gc->data.data[0] = '^';
+ gc->data.data[1] = (ch == 0x7f) ? '?' : ch|0x40;
+ gc->data.size = gc->data.have = 2;
+ gc->data.width = 2;
+ } else
+ utf8_copy(&gc->data, ud);
+ screen_write_cell(ctx, gc);
+ return (1);
+}
+
+/*
+ * Redraw quote indicator '^' if necessary. Return 1 if can continue redrawing,
+ * 0 otherwise.
+ */
+static int
+status_prompt_redraw_quote(const struct client *c, u_int pcursor,
+ struct screen_write_ctx *ctx, u_int offset, u_int pwidth, u_int *width,
+ struct grid_cell *gc)
+{
+ struct utf8_data ud;
+
+ if (c->prompt_flags & PROMPT_QUOTENEXT && ctx->s->cx == pcursor + 1) {
+ utf8_set(&ud, '^');
+ return (status_prompt_redraw_character(ctx, offset, pwidth,
+ width, gc, &ud));
+ }
+ return (1);
+}
+
/* Draw client prompt on status line of present else on last line. */
int
status_prompt_redraw(struct client *c)
@@ -740,8 +789,6 @@ status_prompt_redraw(struct client *c)
u_int pcursor, pwidth, promptline;
struct grid_cell gc;
struct format_tree *ft;
- u_char ch;
- struct utf8_data *ud;
if (c->tty.sx == 0 || c->tty.sy == 0)
return (0);
@@ -788,6 +835,8 @@ status_prompt_redraw(struct client *c)
pcursor = utf8_strwidth(c->prompt_buffer, c->prompt_index);
pwidth = utf8_strwidth(c->prompt_buffer, -1);
+ if (c->prompt_flags & PROMPT_QUOTENEXT)
+ pwidth++;
if (pcursor >= left) {
/*
* The cursor would be outside the screen so start drawing
@@ -799,31 +848,19 @@ status_prompt_redraw(struct client *c)
offset = 0;
if (pwidth > left)
pwidth = left;
- c->prompt_cursor = start + c->prompt_index - offset;
+ c->prompt_cursor = start + pcursor - offset;
width = 0;
for (i = 0; c->prompt_buffer[i].size != 0; i++) {
- ud = &c->prompt_buffer[i];
- if (width < offset) {
- width += ud->width;
- continue;
- }
- if (width >= offset + pwidth)
+ if (!status_prompt_redraw_quote(c, pcursor, &ctx, offset,
+ pwidth, &width, &gc))
break;
- width += ud->width;
- if (width > offset + pwidth)
+ if (!status_prompt_redraw_character(&ctx, offset, pwidth,
+ &width, &gc, &c->prompt_buffer[i]))
break;
-
- ch = *ud->data;
- if (ud->size == 1 && (ch <= 0x1f || ch == 0x7f)) {
- gc.data.data[0] = '^';
- gc.data.data[1] = (ch == 0x7f) ? '?' : ch|0x40;
- gc.data.size = gc.data.have = 2;
- gc.data.width = 2;
- } else
- utf8_copy(&gc.data, ud);
- screen_write_cell(&ctx, &gc);
}
+ status_prompt_redraw_quote(c, pcursor, &ctx, offset, pwidth, &width,
+ &gc);
finished:
screen_write_stop(&ctx);
@@ -1274,7 +1311,6 @@ status_prompt_key(struct client *c, key_code key)
key &= ~KEYC_MASK_FLAGS;
if (c->prompt_flags & (PROMPT_SINGLE|PROMPT_QUOTENEXT)) {
- c->prompt_flags &= ~PROMPT_QUOTENEXT;
if ((key & KEYC_MASK_KEY) == KEYC_BSPACE)
key = 0x7f;
else if ((key & KEYC_MASK_KEY) > 0x7f) {
@@ -1283,6 +1319,7 @@ status_prompt_key(struct client *c, key_code key)
key &= KEYC_MASK_KEY;
} else
key &= (key & KEYC_CTRL) ? 0x1f : KEYC_MASK_KEY;
+ c->prompt_flags &= ~PROMPT_QUOTENEXT;
goto append_key;
}