mirror of
https://github.com/tmux/tmux.git
synced 2026-02-25 04:15:04 +00:00
Merge master.
This commit is contained in:
16
Makefile.am
16
Makefile.am
@@ -20,17 +20,23 @@ LDADD = $(LIBOBJS)
|
||||
|
||||
# Set flags for gcc.
|
||||
if IS_GCC
|
||||
AM_CFLAGS += -std=gnu99 -O2
|
||||
AM_CFLAGS += -std=gnu99
|
||||
if IS_OPTIMIZED
|
||||
AM_CFLAGS += -O2
|
||||
else
|
||||
AM_CFLAGS += -O0
|
||||
endif
|
||||
if IS_DEBUG
|
||||
AM_CFLAGS += -g
|
||||
AM_CFLAGS += -Wno-long-long -Wall -W -Wformat=2
|
||||
AM_CFLAGS += -Wno-long-long -Wall -W -Wformat=2 -Wno-use-after-free
|
||||
AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
|
||||
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
|
||||
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
|
||||
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wno-cast-align
|
||||
AM_CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
|
||||
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k
|
||||
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k -Wno-unknown-warning-option
|
||||
AM_CFLAGS += -Wno-maybe-uninitialized
|
||||
if IS_DARWIN
|
||||
AM_CFLAGS += -Wno-deprecated-declarations -Wno-cast-align -Wno-macro-redefined
|
||||
AM_CFLAGS += -Wno-deprecated-declarations -Wno-macro-redefined
|
||||
endif
|
||||
AM_CPPFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
||||
.name = "command-prompt",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "1bFkliI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||
.usage = "[-1bFkliN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||
.args = { "1beFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||
.usage = "[-1beFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||
" [-T prompt-type] [template]",
|
||||
|
||||
.flags = CMD_CLIENT_TFLAG,
|
||||
@@ -84,7 +84,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct client *tc = cmdq_get_target_client(item);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
const char *type, *s, *input;
|
||||
struct cmd_command_prompt_cdata *cdata;
|
||||
struct cmd_command_prompt_cdata *cdata;
|
||||
char *tmp, *prompts, *prompt, *next_prompt;
|
||||
char *inputs = NULL, *next_input;
|
||||
u_int count = args_count(args);
|
||||
@@ -163,6 +163,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->flags |= PROMPT_INCREMENTAL;
|
||||
else if (args_has(args, 'k'))
|
||||
cdata->flags |= PROMPT_KEY;
|
||||
else if (args_has(args, 'e'))
|
||||
cdata->flags |= PROMPT_BSPACE_EXIT;
|
||||
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
||||
cdata->prompts[0].input, cmd_command_prompt_callback,
|
||||
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
||||
@@ -234,7 +236,7 @@ out:
|
||||
static void
|
||||
cmd_command_prompt_free(void *data)
|
||||
{
|
||||
struct cmd_command_prompt_cdata *cdata = data;
|
||||
struct cmd_command_prompt_cdata *cdata = data;
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < cdata->count; i++) {
|
||||
|
||||
@@ -64,6 +64,15 @@ AC_ARG_ENABLE(
|
||||
)
|
||||
AM_CONDITIONAL(IS_DEBUG, test "x$enable_debug" = xyes)
|
||||
|
||||
# Is this --enable-optimizations?
|
||||
AC_ARG_ENABLE(
|
||||
optimizations,
|
||||
AS_HELP_STRING(--enable-optimizations, enable optimization build flags),
|
||||
,
|
||||
enable_optimizations=yes
|
||||
)
|
||||
AM_CONDITIONAL(IS_OPTIMIZED, test "x$enable_optimizations" = xyes)
|
||||
|
||||
# Is this a static build?
|
||||
AC_ARG_ENABLE(
|
||||
static,
|
||||
|
||||
19
format.c
19
format.c
@@ -454,6 +454,20 @@ format_job_tidy(struct format_job_tree *jobs, int force)
|
||||
}
|
||||
}
|
||||
|
||||
/* Work around needless -Wformat-nonliteral gcc warning. */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
#endif
|
||||
static size_t
|
||||
format_strftime(char *s, size_t max, const char *fmt, const struct tm *tm)
|
||||
{
|
||||
return (strftime(s, max, fmt, tm));
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/* Tidy old jobs for all clients. */
|
||||
void
|
||||
format_tidy_jobs(void)
|
||||
@@ -3963,7 +3977,7 @@ found:
|
||||
else {
|
||||
if (time_format != NULL) {
|
||||
localtime_r(&t, &tm);
|
||||
strftime(s, sizeof s, time_format, &tm);
|
||||
format_strftime(s, sizeof s, time_format, &tm);
|
||||
} else {
|
||||
ctime_r(&t, s);
|
||||
s[strcspn(s, "\n")] = '\0';
|
||||
@@ -5540,7 +5554,8 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
||||
es->time = time(NULL);
|
||||
localtime_r(&es->time, &es->tm);
|
||||
}
|
||||
if (strftime(expanded, sizeof expanded, fmt, &es->tm) == 0) {
|
||||
if (format_strftime(expanded, sizeof expanded, fmt,
|
||||
&es->tm) == 0) {
|
||||
format_log(es, "format is too long");
|
||||
return (xstrdup(""));
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}' '<' {send -X history-top}" \
|
||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
||||
" ''" \
|
||||
" '#{?#{&&:#{buffer_size},#{!:#{pane_in_mode}}},Paste #[underscore]#{=/9/...:buffer_sample},}' 'p' {paste-buffer}" \
|
||||
" ''" \
|
||||
" '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {if -F '#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}' 'copy-mode -t='; send -Xt= search-backward -- \"#{q:mouse_word}\"}" \
|
||||
" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {copy-mode -q; send-keys -l -- \"#{q:mouse_word}\"}" \
|
||||
" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \
|
||||
|
||||
52
regress/border-arrows.sh
Normal file
52
regress/border-arrows.sh
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Test for GitHub issue #4780 - pane-border-indicators both arrows missing
|
||||
# on second pane in a two-pane horizontal split.
|
||||
#
|
||||
# When pane-border-indicators is set to "both", arrow indicators should
|
||||
# appear when EITHER pane is selected. Before the fix, arrows only appeared
|
||||
# when the LEFT pane was selected.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX_OUTER="$TEST_TMUX -Ltest2"
|
||||
$TMUX_OUTER kill-server 2>/dev/null
|
||||
|
||||
trap "$TMUX kill-server 2>/dev/null; $TMUX_OUTER kill-server 2>/dev/null" 0 1 15
|
||||
|
||||
# Start outer tmux that will capture the inner tmux's rendering
|
||||
$TMUX_OUTER -f/dev/null new -d -x80 -y24 "$TMUX -f/dev/null new -x78 -y22" || exit 1
|
||||
sleep 1
|
||||
|
||||
# Set pane-border-indicators to "both" in inner tmux
|
||||
$TMUX set -g pane-border-indicators both || exit 1
|
||||
|
||||
# Create horizontal split (two panes side by side)
|
||||
$TMUX splitw -h || exit 1
|
||||
sleep 1
|
||||
|
||||
# Helper to check for arrow characters in captured output
|
||||
has_arrow() {
|
||||
echo "$1" | grep -qE '(←|→|↑|↓)'
|
||||
}
|
||||
|
||||
# Test 1: Select left pane (pane 0) and check for arrows
|
||||
$TMUX selectp -t 0
|
||||
sleep 1
|
||||
left_output=$($TMUX_OUTER capturep -Cep 2>/dev/null)
|
||||
has_arrow "$left_output" || exit 1
|
||||
|
||||
# Test 2: Select right pane (pane 1) and check for arrows
|
||||
# This is the case that failed before the fix
|
||||
$TMUX selectp -t 1
|
||||
sleep 1
|
||||
right_output=$($TMUX_OUTER capturep -Cep 2>/dev/null)
|
||||
has_arrow "$right_output" || exit 1
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX_OUTER kill-server 2>/dev/null
|
||||
exit 0
|
||||
106
screen-redraw.c
106
screen-redraw.c
@@ -98,7 +98,7 @@ screen_redraw_border_set(struct window *w, struct window_pane *wp,
|
||||
}
|
||||
}
|
||||
|
||||
/* Return if window has only two panes. */
|
||||
/* Return 1 if window has only two panes. */
|
||||
static int
|
||||
screen_redraw_two_panes(struct window *w, enum layout_type *type)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
if ((int)px == wp->xoff + (int)wp->sx + sb_w - 1)
|
||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
||||
}
|
||||
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT or none. */
|
||||
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT or disabled */
|
||||
if (wp->xoff == 0 && px == wp->sx + sb_w)
|
||||
if (!hsplit || (hsplit && py <= wp->sy / 2))
|
||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
||||
@@ -900,6 +900,79 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x,
|
||||
return (&wp->border_gc);
|
||||
}
|
||||
|
||||
/* Draw arrow indicator if enabled. */
|
||||
static void
|
||||
screen_redraw_draw_border_arrows(struct screen_redraw_ctx *ctx, u_int i,
|
||||
u_int j, u_int cell_type, struct window_pane *wp,
|
||||
struct window_pane *active, struct grid_cell *gc)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct session *s = c->session;
|
||||
struct window *w = s->curw->window;
|
||||
struct options *oo = w->options;
|
||||
u_int x = ctx->ox + i, y = ctx->oy + j;
|
||||
int value, arrows = 0, border;
|
||||
enum layout_type type;
|
||||
|
||||
if (wp == NULL)
|
||||
return;
|
||||
if ((int)i != wp->xoff + 1 && (int)j != wp->yoff + 1)
|
||||
return;
|
||||
|
||||
value = options_get_number(oo, "pane-border-indicators");
|
||||
if (value != PANE_BORDER_ARROWS && value != PANE_BORDER_BOTH)
|
||||
return;
|
||||
|
||||
border = screen_redraw_pane_border(ctx, active, x, y);
|
||||
if (border == SCREEN_REDRAW_INSIDE)
|
||||
return;
|
||||
|
||||
if ((int)i == wp->xoff + 1) {
|
||||
if (border == SCREEN_REDRAW_OUTSIDE) {
|
||||
if (screen_redraw_two_panes(wp->window, &type)) {
|
||||
if (active == TAILQ_FIRST(&w->panes))
|
||||
border = SCREEN_REDRAW_BORDER_BOTTOM;
|
||||
else
|
||||
border = SCREEN_REDRAW_BORDER_TOP;
|
||||
arrows = 1;
|
||||
}
|
||||
} else {
|
||||
if (cell_type == CELL_LEFTRIGHT)
|
||||
arrows = 1;
|
||||
else if (cell_type == CELL_TOPJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_BOTTOM)
|
||||
arrows = 1;
|
||||
else if (cell_type == CELL_BOTTOMJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_TOP)
|
||||
arrows = 1;
|
||||
}
|
||||
}
|
||||
if ((int)j == wp->yoff + 1) {
|
||||
if (border == SCREEN_REDRAW_OUTSIDE) {
|
||||
if (screen_redraw_two_panes(wp->window, 0)) {
|
||||
if (active == TAILQ_FIRST(&w->panes))
|
||||
border = SCREEN_REDRAW_BORDER_RIGHT;
|
||||
else
|
||||
border = SCREEN_REDRAW_BORDER_LEFT;
|
||||
arrows = 1;
|
||||
}
|
||||
} else {
|
||||
if (cell_type == CELL_TOPBOTTOM)
|
||||
arrows = 1;
|
||||
else if (cell_type == CELL_LEFTJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_RIGHT)
|
||||
arrows = 1;
|
||||
else if (cell_type == CELL_RIGHTJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_LEFT)
|
||||
arrows = 1;
|
||||
}
|
||||
}
|
||||
if (arrows) {
|
||||
gc->attr |= GRID_ATTR_CHARSET;
|
||||
utf8_set(&gc->data, BORDER_MARKERS[border]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a border cell. */
|
||||
static void
|
||||
screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
||||
@@ -915,7 +988,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
||||
const struct grid_cell *tmp;
|
||||
struct overlay_ranges r;
|
||||
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
|
||||
int arrows = 0, border, isolates;
|
||||
int isolates;
|
||||
|
||||
if (c->overlay_check != NULL) {
|
||||
c->overlay_check(c, c->overlay_data, x, y, 1, &r);
|
||||
@@ -963,32 +1036,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
||||
if (isolates)
|
||||
tty_puts(tty, END_ISOLATE);
|
||||
|
||||
switch (options_get_number(oo, "pane-border-indicators")) {
|
||||
case PANE_BORDER_ARROWS:
|
||||
case PANE_BORDER_BOTH:
|
||||
arrows = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wp != NULL && arrows) {
|
||||
border = screen_redraw_pane_border(ctx, active, x, y);
|
||||
if ((((int)i == wp->xoff + 1 &&
|
||||
(cell_type == CELL_LEFTRIGHT ||
|
||||
(cell_type == CELL_TOPJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_BOTTOM) ||
|
||||
(cell_type == CELL_BOTTOMJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_TOP))) ||
|
||||
((int)j == wp->yoff + 1 &&
|
||||
(cell_type == CELL_TOPBOTTOM ||
|
||||
(cell_type == CELL_LEFTJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_RIGHT) ||
|
||||
(cell_type == CELL_RIGHTJOIN &&
|
||||
border == SCREEN_REDRAW_BORDER_LEFT)))) &&
|
||||
screen_redraw_check_is(ctx, x, y, active)) {
|
||||
gc.attr |= GRID_ATTR_CHARSET;
|
||||
utf8_set(&gc.data, BORDER_MARKERS[border]);
|
||||
}
|
||||
}
|
||||
screen_redraw_draw_border_arrows(ctx, i, j, cell_type, wp, active, &gc);
|
||||
|
||||
tty_cell(tty, &gc, &grid_default_cell, NULL, NULL);
|
||||
if (isolates)
|
||||
|
||||
103
screen-write.c
103
screen-write.c
@@ -25,6 +25,8 @@
|
||||
|
||||
static struct screen_write_citem *screen_write_collect_trim(
|
||||
struct screen_write_ctx *, u_int, u_int, u_int, int *);
|
||||
static void screen_write_collect_insert(struct screen_write_ctx *,
|
||||
struct screen_write_citem *);
|
||||
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
||||
u_int);
|
||||
static void screen_write_collect_scroll(struct screen_write_ctx *, u_int);
|
||||
@@ -1334,7 +1336,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_line *gl;
|
||||
u_int sx = screen_size_x(s);
|
||||
struct screen_write_citem *ci = ctx->item, *before;
|
||||
struct screen_write_citem *ci = ctx->item;
|
||||
|
||||
if (s->cx == 0) {
|
||||
screen_write_clearline(ctx, bg);
|
||||
@@ -1352,16 +1354,11 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
|
||||
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
|
||||
|
||||
before = screen_write_collect_trim(ctx, s->cy, s->cx, sx - s->cx, NULL);
|
||||
ci->x = s->cx;
|
||||
ci->used = sx - s->cx;
|
||||
ci->type = CLEAR;
|
||||
ci->bg = bg;
|
||||
if (before == NULL)
|
||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
|
||||
else
|
||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
||||
ctx->item = screen_write_get_citem();
|
||||
screen_write_collect_insert(ctx, ci);
|
||||
}
|
||||
|
||||
/* Clear to start of line from cursor. */
|
||||
@@ -1370,7 +1367,7 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
u_int sx = screen_size_x(s);
|
||||
struct screen_write_citem *ci = ctx->item, *before;
|
||||
struct screen_write_citem *ci = ctx->item;
|
||||
|
||||
if (s->cx >= sx - 1) {
|
||||
screen_write_clearline(ctx, bg);
|
||||
@@ -1387,16 +1384,11 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
else
|
||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
||||
|
||||
before = screen_write_collect_trim(ctx, s->cy, 0, s->cx + 1, NULL);
|
||||
ci->x = 0;
|
||||
ci->used = s->cx + 1;
|
||||
ci->type = CLEAR;
|
||||
ci->bg = bg;
|
||||
if (before == NULL)
|
||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
|
||||
else
|
||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
||||
ctx->item = screen_write_get_citem();
|
||||
screen_write_collect_insert(ctx, ci);
|
||||
}
|
||||
|
||||
/* Move cursor to px,py. */
|
||||
@@ -1892,6 +1884,8 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
|
||||
last = UINT_MAX;
|
||||
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
||||
log_debug("collect list: x=%u (last %u), y=%u, used=%u",
|
||||
ci->x, last, y, ci->used);
|
||||
if (last != UINT_MAX && ci->x <= last) {
|
||||
fatalx("collect list not in order: %u <= %u",
|
||||
ci->x, last);
|
||||
@@ -1948,29 +1942,39 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
log_debug("%s: flushed %u items (%s)", __func__, items, from);
|
||||
}
|
||||
|
||||
/* Finish and store collected cells. */
|
||||
/* Insert an item on current line. */
|
||||
void
|
||||
screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
screen_write_collect_insert(struct screen_write_ctx *ctx,
|
||||
struct screen_write_citem *ci)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct screen_write_citem *ci = ctx->item, *nci, *before;
|
||||
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||
struct grid_cell gc;
|
||||
u_int xx;
|
||||
int wrapped = ci->wrapped;
|
||||
struct screen_write_citem *before;
|
||||
|
||||
if (ci->used == 0)
|
||||
return;
|
||||
|
||||
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
|
||||
&wrapped);
|
||||
ci->x = s->cx;
|
||||
ci->wrapped = wrapped;
|
||||
before = screen_write_collect_trim(ctx, s->cy, ci->x, ci->used,
|
||||
&ci->wrapped);
|
||||
if (before == NULL)
|
||||
TAILQ_INSERT_TAIL(&cl->items, ci, entry);
|
||||
else
|
||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
||||
ctx->item = screen_write_get_citem();
|
||||
}
|
||||
|
||||
/* Finish and store collected cells. */
|
||||
void
|
||||
screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct screen_write_citem *ci = ctx->item, *bci = NULL, *aci;
|
||||
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||
struct grid_cell gc;
|
||||
u_int xx;
|
||||
|
||||
if (ci->used == 0)
|
||||
return;
|
||||
|
||||
ci->x = s->cx;
|
||||
screen_write_collect_insert(ctx, ci);
|
||||
|
||||
log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
|
||||
(int)ci->used, cl->data + ci->x, s->cx, s->cy);
|
||||
@@ -1982,27 +1986,28 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
break;
|
||||
grid_view_set_cell(s->grid, xx, s->cy,
|
||||
&grid_default_cell);
|
||||
log_debug("%s: padding erased (before) at %u",
|
||||
__func__, xx);
|
||||
log_debug("%s: padding erased (before) at %u (cx %u)",
|
||||
__func__, xx, s->cx);
|
||||
}
|
||||
if (xx != s->cx) {
|
||||
if (xx == 0)
|
||||
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
||||
if (gc.data.width > 1) {
|
||||
if (gc.data.width > 1 ||
|
||||
(gc.flags & GRID_FLAG_PADDING)) {
|
||||
grid_view_set_cell(s->grid, xx, s->cy,
|
||||
&grid_default_cell);
|
||||
log_debug("%s: padding erased (before) at %u",
|
||||
__func__, xx);
|
||||
log_debug("%s: padding erased (before) at %u "
|
||||
"(cx %u)", __func__, xx, s->cx);
|
||||
}
|
||||
}
|
||||
if (xx != s->cx) {
|
||||
nci = ctx->item;
|
||||
nci->type = CLEAR;
|
||||
nci->x = xx;
|
||||
nci->bg = 8;
|
||||
nci->used = s->cx - xx;
|
||||
TAILQ_INSERT_BEFORE(ci, nci, entry);
|
||||
ctx->item = screen_write_get_citem();
|
||||
bci = ctx->item;
|
||||
bci->type = CLEAR;
|
||||
bci->x = xx;
|
||||
bci->bg = 8;
|
||||
bci->used = s->cx - xx;
|
||||
log_debug("%s: padding erased (before): from %u, "
|
||||
"size %u", __func__, bci->x, bci->used);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2013,6 +2018,8 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
|
||||
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
||||
ci->used);
|
||||
if (bci != NULL)
|
||||
screen_write_collect_insert(ctx, bci);
|
||||
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
||||
|
||||
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
||||
@@ -2020,16 +2027,18 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
if (~gc.flags & GRID_FLAG_PADDING)
|
||||
break;
|
||||
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
||||
log_debug("%s: padding erased (after) at %u", __func__, xx);
|
||||
log_debug("%s: padding erased (after) at %u (cx %u)",
|
||||
__func__, xx, s->cx);
|
||||
}
|
||||
if (xx != s->cx) {
|
||||
nci = ctx->item;
|
||||
nci->type = CLEAR;
|
||||
nci->x = s->cx;
|
||||
nci->bg = 8;
|
||||
nci->used = xx - s->cx;
|
||||
TAILQ_INSERT_AFTER(&cl->items, ci, nci, entry);
|
||||
ctx->item = screen_write_get_citem();
|
||||
aci = ctx->item;
|
||||
aci->type = CLEAR;
|
||||
aci->x = s->cx;
|
||||
aci->bg = 8;
|
||||
aci->used = xx - s->cx;
|
||||
log_debug("%s: padding erased (after): from %u, size %u",
|
||||
__func__, aci->x, aci->used);
|
||||
screen_write_collect_insert(ctx, aci);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,6 +311,8 @@ server_client_create(int fd)
|
||||
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
||||
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
||||
|
||||
c->click_wp = -1;
|
||||
|
||||
TAILQ_INIT(&c->input_requests);
|
||||
|
||||
TAILQ_INSERT_TAIL(&clients, c, entry);
|
||||
@@ -759,21 +761,17 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
||||
if (c->flags & CLIENT_DOUBLECLICK) {
|
||||
evtimer_del(&c->click_timer);
|
||||
c->flags &= ~CLIENT_DOUBLECLICK;
|
||||
if (m->b == c->click_button) {
|
||||
type = SECOND;
|
||||
x = m->x, y = m->y, b = m->b;
|
||||
log_debug("second-click at %u,%u", x, y);
|
||||
c->flags |= CLIENT_TRIPLECLICK;
|
||||
}
|
||||
type = SECOND;
|
||||
x = m->x, y = m->y, b = m->b;
|
||||
log_debug("second-click at %u,%u", x, y);
|
||||
c->flags |= CLIENT_TRIPLECLICK;
|
||||
} else if (c->flags & CLIENT_TRIPLECLICK) {
|
||||
evtimer_del(&c->click_timer);
|
||||
c->flags &= ~CLIENT_TRIPLECLICK;
|
||||
if (m->b == c->click_button) {
|
||||
type = TRIPLE;
|
||||
x = m->x, y = m->y, b = m->b;
|
||||
log_debug("triple-click at %u,%u", x, y);
|
||||
goto have_event;
|
||||
}
|
||||
type = TRIPLE;
|
||||
x = m->x, y = m->y, b = m->b;
|
||||
log_debug("triple-click at %u,%u", x, y);
|
||||
goto have_event;
|
||||
}
|
||||
|
||||
/* DOWN is the only remaining event type. */
|
||||
@@ -783,17 +781,6 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
||||
log_debug("down at %u,%u", x, y);
|
||||
c->flags |= CLIENT_DOUBLECLICK;
|
||||
}
|
||||
|
||||
if (KEYC_CLICK_TIMEOUT != 0) {
|
||||
memcpy(&c->click_event, m, sizeof c->click_event);
|
||||
c->click_button = m->b;
|
||||
|
||||
log_debug("click timer started");
|
||||
tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
|
||||
tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
|
||||
evtimer_del(&c->click_timer);
|
||||
evtimer_add(&c->click_timer, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
have_event:
|
||||
@@ -914,6 +901,34 @@ have_event:
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset click type or add a click timer if needed. */
|
||||
if (type == DOWN ||
|
||||
type == SECOND ||
|
||||
type == TRIPLE) {
|
||||
if (type != DOWN &&
|
||||
(m->b != c->click_button ||
|
||||
where != (enum mouse_where)c->click_where ||
|
||||
m->wp != c->click_wp)) {
|
||||
type = DOWN;
|
||||
log_debug("click sequence reset at %u,%u", x, y);
|
||||
c->flags &= ~CLIENT_TRIPLECLICK;
|
||||
c->flags |= CLIENT_DOUBLECLICK;
|
||||
}
|
||||
|
||||
if (type != TRIPLE && KEYC_CLICK_TIMEOUT != 0) {
|
||||
memcpy(&c->click_event, m, sizeof c->click_event);
|
||||
c->click_button = m->b;
|
||||
c->click_where = where;
|
||||
c->click_wp = m->wp;
|
||||
|
||||
log_debug("click timer started");
|
||||
tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
|
||||
tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
|
||||
evtimer_del(&c->click_timer);
|
||||
evtimer_add(&c->click_timer, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop dragging if needed. */
|
||||
if (type != DRAG &&
|
||||
type != WHEEL &&
|
||||
|
||||
5
status.c
5
status.c
@@ -1383,6 +1383,11 @@ process_key:
|
||||
break;
|
||||
case KEYC_BSPACE:
|
||||
case 'h'|KEYC_CTRL:
|
||||
if (c->prompt_flags & PROMPT_BSPACE_EXIT && size == 0) {
|
||||
if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0)
|
||||
status_prompt_clear(c);
|
||||
break;
|
||||
}
|
||||
if (c->prompt_index != 0) {
|
||||
if (c->prompt_index == size)
|
||||
c->prompt_buffer[--c->prompt_index].size = 0;
|
||||
|
||||
6
tmux.1
6
tmux.1
@@ -6718,7 +6718,7 @@ See
|
||||
for possible values for
|
||||
.Ar prompt-type .
|
||||
.It Xo Ic command-prompt
|
||||
.Op Fl 1bFiklN
|
||||
.Op Fl 1beFiklN
|
||||
.Op Fl I Ar inputs
|
||||
.Op Fl p Ar prompts
|
||||
.Op Fl t Ar target-client
|
||||
@@ -6791,6 +6791,10 @@ makes the prompt only accept numeric key presses.
|
||||
.Fl i
|
||||
executes the command every time the prompt input changes instead of when the
|
||||
user exits the command prompt.
|
||||
.Fl e
|
||||
makes
|
||||
.Em BSpace
|
||||
cancel an empty prompt.
|
||||
.Pp
|
||||
.Fl T
|
||||
tells
|
||||
|
||||
3
tmux.h
3
tmux.h
@@ -1984,6 +1984,8 @@ struct client {
|
||||
struct event repeat_timer;
|
||||
|
||||
struct event click_timer;
|
||||
int click_where;
|
||||
int click_wp;
|
||||
u_int click_button;
|
||||
struct mouse_event click_event;
|
||||
|
||||
@@ -2094,6 +2096,7 @@ struct client {
|
||||
#define PROMPT_KEY 0x10
|
||||
#define PROMPT_ACCEPT 0x20
|
||||
#define PROMPT_QUOTENEXT 0x40
|
||||
#define PROMPT_BSPACE_EXIT 0x80
|
||||
int prompt_flags;
|
||||
enum prompt_type prompt_type;
|
||||
int prompt_cursor;
|
||||
|
||||
@@ -228,7 +228,6 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
||||
struct screen *s = &data->screen;
|
||||
struct grid_cell gc;
|
||||
char tim[64], *ptr;
|
||||
const char *timeformat;
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
u_int i, j, x, y, idx;
|
||||
@@ -242,20 +241,18 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
||||
tm = localtime(&t);
|
||||
if (style == 0 || style == 2) {
|
||||
if (style == 2)
|
||||
timeformat = "%l:%M:%S ";
|
||||
strftime(tim, sizeof tim, "%l:%M:%S ", localtime(&t));
|
||||
else
|
||||
timeformat = "%l:%M ";
|
||||
strftime(tim, sizeof tim, timeformat, localtime(&t));
|
||||
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 {
|
||||
if (style == 3)
|
||||
timeformat = "%H:%M:%S";
|
||||
strftime(tim, sizeof tim, "%H:%M:%S", tm);
|
||||
else
|
||||
timeformat = "%H:%M";
|
||||
strftime(tim, sizeof tim, timeformat, tm);
|
||||
strftime(tim, sizeof tim, "%H:%M", tm);
|
||||
}
|
||||
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
@@ -3237,6 +3237,15 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
||||
window_pane_reset_mode(wp);
|
||||
else if (action == WINDOW_COPY_CMD_REDRAW)
|
||||
window_copy_redraw_screen(wme);
|
||||
else if (action == WINDOW_COPY_CMD_NOTHING) {
|
||||
/*
|
||||
* Nothing is not actually nothing - most commands at least
|
||||
* move the cursor (what would be the point of a command that
|
||||
* literally does nothing?) and in that case we need to redraw
|
||||
* the first line to update the indicator.
|
||||
*/
|
||||
window_copy_redraw_lines(wme, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user