mirror of
https://github.com/tmux/tmux.git
synced 2026-04-02 02:16:27 +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.
|
# Set flags for gcc.
|
||||||
if IS_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
|
if IS_DEBUG
|
||||||
AM_CFLAGS += -g
|
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 += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
|
||||||
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
|
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 += -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
|
if IS_DARWIN
|
||||||
AM_CFLAGS += -Wno-deprecated-declarations -Wno-cast-align -Wno-macro-redefined
|
AM_CFLAGS += -Wno-deprecated-declarations -Wno-macro-redefined
|
||||||
endif
|
endif
|
||||||
AM_CPPFLAGS += -DDEBUG
|
AM_CPPFLAGS += -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
|||||||
.name = "command-prompt",
|
.name = "command-prompt",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "1bFkliI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
.args = { "1beFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||||
.usage = "[-1bFkliN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
.usage = "[-1beFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [-T prompt-type] [template]",
|
" [-T prompt-type] [template]",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_TFLAG,
|
.flags = CMD_CLIENT_TFLAG,
|
||||||
@@ -163,6 +163,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata->flags |= PROMPT_INCREMENTAL;
|
cdata->flags |= PROMPT_INCREMENTAL;
|
||||||
else if (args_has(args, 'k'))
|
else if (args_has(args, 'k'))
|
||||||
cdata->flags |= PROMPT_KEY;
|
cdata->flags |= PROMPT_KEY;
|
||||||
|
else if (args_has(args, 'e'))
|
||||||
|
cdata->flags |= PROMPT_BSPACE_EXIT;
|
||||||
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
||||||
cdata->prompts[0].input, cmd_command_prompt_callback,
|
cdata->prompts[0].input, cmd_command_prompt_callback,
|
||||||
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
||||||
|
|||||||
@@ -64,6 +64,15 @@ AC_ARG_ENABLE(
|
|||||||
)
|
)
|
||||||
AM_CONDITIONAL(IS_DEBUG, test "x$enable_debug" = xyes)
|
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?
|
# Is this a static build?
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
static,
|
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. */
|
/* Tidy old jobs for all clients. */
|
||||||
void
|
void
|
||||||
format_tidy_jobs(void)
|
format_tidy_jobs(void)
|
||||||
@@ -3963,7 +3977,7 @@ found:
|
|||||||
else {
|
else {
|
||||||
if (time_format != NULL) {
|
if (time_format != NULL) {
|
||||||
localtime_r(&t, &tm);
|
localtime_r(&t, &tm);
|
||||||
strftime(s, sizeof s, time_format, &tm);
|
format_strftime(s, sizeof s, time_format, &tm);
|
||||||
} else {
|
} else {
|
||||||
ctime_r(&t, s);
|
ctime_r(&t, s);
|
||||||
s[strcspn(s, "\n")] = '\0';
|
s[strcspn(s, "\n")] = '\0';
|
||||||
@@ -5540,7 +5554,8 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
es->time = time(NULL);
|
es->time = time(NULL);
|
||||||
localtime_r(&es->time, &es->tm);
|
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");
|
format_log(es, "format is too long");
|
||||||
return (xstrdup(""));
|
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 Top,}' '<' {send -X history-top}" \
|
||||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
" '#{?#{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,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,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}\"}" \
|
" '#{?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
|
static int
|
||||||
screen_redraw_two_panes(struct window *w, enum layout_type *type)
|
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)
|
if ((int)px == wp->xoff + (int)wp->sx + sb_w - 1)
|
||||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
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 (wp->xoff == 0 && px == wp->sx + sb_w)
|
||||||
if (!hsplit || (hsplit && py <= wp->sy / 2))
|
if (!hsplit || (hsplit && py <= wp->sy / 2))
|
||||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
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);
|
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. */
|
/* Draw a border cell. */
|
||||||
static void
|
static void
|
||||||
screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
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;
|
const struct grid_cell *tmp;
|
||||||
struct overlay_ranges r;
|
struct overlay_ranges r;
|
||||||
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
|
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
|
||||||
int arrows = 0, border, isolates;
|
int isolates;
|
||||||
|
|
||||||
if (c->overlay_check != NULL) {
|
if (c->overlay_check != NULL) {
|
||||||
c->overlay_check(c, c->overlay_data, x, y, 1, &r);
|
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)
|
if (isolates)
|
||||||
tty_puts(tty, END_ISOLATE);
|
tty_puts(tty, END_ISOLATE);
|
||||||
|
|
||||||
switch (options_get_number(oo, "pane-border-indicators")) {
|
screen_redraw_draw_border_arrows(ctx, i, j, cell_type, wp, active, &gc);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tty_cell(tty, &gc, &grid_default_cell, NULL, NULL);
|
tty_cell(tty, &gc, &grid_default_cell, NULL, NULL);
|
||||||
if (isolates)
|
if (isolates)
|
||||||
|
|||||||
103
screen-write.c
103
screen-write.c
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
static struct screen_write_citem *screen_write_collect_trim(
|
static struct screen_write_citem *screen_write_collect_trim(
|
||||||
struct screen_write_ctx *, u_int, u_int, u_int, int *);
|
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,
|
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
static void screen_write_collect_scroll(struct screen_write_ctx *, 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 screen *s = ctx->s;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
u_int sx = screen_size_x(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 == 0) {
|
if (s->cx == 0) {
|
||||||
screen_write_clearline(ctx, bg);
|
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);
|
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->x = s->cx;
|
||||||
ci->used = sx - s->cx;
|
ci->used = sx - s->cx;
|
||||||
ci->type = CLEAR;
|
ci->type = CLEAR;
|
||||||
ci->bg = bg;
|
ci->bg = bg;
|
||||||
if (before == NULL)
|
screen_write_collect_insert(ctx, ci);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear to start of line from cursor. */
|
/* 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;
|
struct screen *s = ctx->s;
|
||||||
u_int sx = screen_size_x(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) {
|
if (s->cx >= sx - 1) {
|
||||||
screen_write_clearline(ctx, bg);
|
screen_write_clearline(ctx, bg);
|
||||||
@@ -1387,16 +1384,11 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
else
|
else
|
||||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
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->x = 0;
|
||||||
ci->used = s->cx + 1;
|
ci->used = s->cx + 1;
|
||||||
ci->type = CLEAR;
|
ci->type = CLEAR;
|
||||||
ci->bg = bg;
|
ci->bg = bg;
|
||||||
if (before == NULL)
|
screen_write_collect_insert(ctx, ci);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move cursor to px,py. */
|
/* Move cursor to px,py. */
|
||||||
@@ -1892,6 +1884,8 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
|
|
||||||
last = UINT_MAX;
|
last = UINT_MAX;
|
||||||
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
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) {
|
if (last != UINT_MAX && ci->x <= last) {
|
||||||
fatalx("collect list not in order: %u <= %u",
|
fatalx("collect list not in order: %u <= %u",
|
||||||
ci->x, last);
|
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);
|
log_debug("%s: flushed %u items (%s)", __func__, items, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish and store collected cells. */
|
/* Insert an item on current line. */
|
||||||
void
|
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 *s = ctx->s;
|
||||||
struct screen_write_citem *ci = ctx->item, *nci, *before;
|
|
||||||
struct screen_write_cline *cl = &s->write_list[s->cy];
|
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||||
struct grid_cell gc;
|
struct screen_write_citem *before;
|
||||||
u_int xx;
|
|
||||||
int wrapped = ci->wrapped;
|
|
||||||
|
|
||||||
if (ci->used == 0)
|
before = screen_write_collect_trim(ctx, s->cy, ci->x, ci->used,
|
||||||
return;
|
&ci->wrapped);
|
||||||
|
|
||||||
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
|
|
||||||
&wrapped);
|
|
||||||
ci->x = s->cx;
|
|
||||||
ci->wrapped = wrapped;
|
|
||||||
if (before == NULL)
|
if (before == NULL)
|
||||||
TAILQ_INSERT_TAIL(&cl->items, ci, entry);
|
TAILQ_INSERT_TAIL(&cl->items, ci, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
TAILQ_INSERT_BEFORE(before, ci, entry);
|
||||||
ctx->item = screen_write_get_citem();
|
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,
|
log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
|
||||||
(int)ci->used, cl->data + ci->x, s->cx, s->cy);
|
(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;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy,
|
grid_view_set_cell(s->grid, xx, s->cy,
|
||||||
&grid_default_cell);
|
&grid_default_cell);
|
||||||
log_debug("%s: padding erased (before) at %u",
|
log_debug("%s: padding erased (before) at %u (cx %u)",
|
||||||
__func__, xx);
|
__func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
if (xx != s->cx) {
|
if (xx != s->cx) {
|
||||||
if (xx == 0)
|
if (xx == 0)
|
||||||
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
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_view_set_cell(s->grid, xx, s->cy,
|
||||||
&grid_default_cell);
|
&grid_default_cell);
|
||||||
log_debug("%s: padding erased (before) at %u",
|
log_debug("%s: padding erased (before) at %u "
|
||||||
__func__, xx);
|
"(cx %u)", __func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xx != s->cx) {
|
if (xx != s->cx) {
|
||||||
nci = ctx->item;
|
bci = ctx->item;
|
||||||
nci->type = CLEAR;
|
bci->type = CLEAR;
|
||||||
nci->x = xx;
|
bci->x = xx;
|
||||||
nci->bg = 8;
|
bci->bg = 8;
|
||||||
nci->used = s->cx - xx;
|
bci->used = s->cx - xx;
|
||||||
TAILQ_INSERT_BEFORE(ci, nci, entry);
|
log_debug("%s: padding erased (before): from %u, "
|
||||||
ctx->item = screen_write_get_citem();
|
"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,
|
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
||||||
ci->used);
|
ci->used);
|
||||||
|
if (bci != NULL)
|
||||||
|
screen_write_collect_insert(ctx, bci);
|
||||||
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
||||||
|
|
||||||
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
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)
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
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) {
|
if (xx != s->cx) {
|
||||||
nci = ctx->item;
|
aci = ctx->item;
|
||||||
nci->type = CLEAR;
|
aci->type = CLEAR;
|
||||||
nci->x = s->cx;
|
aci->x = s->cx;
|
||||||
nci->bg = 8;
|
aci->bg = 8;
|
||||||
nci->used = xx - s->cx;
|
aci->used = xx - s->cx;
|
||||||
TAILQ_INSERT_AFTER(&cl->items, ci, nci, entry);
|
log_debug("%s: padding erased (after): from %u, size %u",
|
||||||
ctx->item = screen_write_get_citem();
|
__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->repeat_timer, server_client_repeat_timer, c);
|
||||||
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
||||||
|
|
||||||
|
c->click_wp = -1;
|
||||||
|
|
||||||
TAILQ_INIT(&c->input_requests);
|
TAILQ_INIT(&c->input_requests);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&clients, c, entry);
|
TAILQ_INSERT_TAIL(&clients, c, entry);
|
||||||
@@ -759,22 +761,18 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
|||||||
if (c->flags & CLIENT_DOUBLECLICK) {
|
if (c->flags & CLIENT_DOUBLECLICK) {
|
||||||
evtimer_del(&c->click_timer);
|
evtimer_del(&c->click_timer);
|
||||||
c->flags &= ~CLIENT_DOUBLECLICK;
|
c->flags &= ~CLIENT_DOUBLECLICK;
|
||||||
if (m->b == c->click_button) {
|
|
||||||
type = SECOND;
|
type = SECOND;
|
||||||
x = m->x, y = m->y, b = m->b;
|
x = m->x, y = m->y, b = m->b;
|
||||||
log_debug("second-click at %u,%u", x, y);
|
log_debug("second-click at %u,%u", x, y);
|
||||||
c->flags |= CLIENT_TRIPLECLICK;
|
c->flags |= CLIENT_TRIPLECLICK;
|
||||||
}
|
|
||||||
} else if (c->flags & CLIENT_TRIPLECLICK) {
|
} else if (c->flags & CLIENT_TRIPLECLICK) {
|
||||||
evtimer_del(&c->click_timer);
|
evtimer_del(&c->click_timer);
|
||||||
c->flags &= ~CLIENT_TRIPLECLICK;
|
c->flags &= ~CLIENT_TRIPLECLICK;
|
||||||
if (m->b == c->click_button) {
|
|
||||||
type = TRIPLE;
|
type = TRIPLE;
|
||||||
x = m->x, y = m->y, b = m->b;
|
x = m->x, y = m->y, b = m->b;
|
||||||
log_debug("triple-click at %u,%u", x, y);
|
log_debug("triple-click at %u,%u", x, y);
|
||||||
goto have_event;
|
goto have_event;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* DOWN is the only remaining event type. */
|
/* DOWN is the only remaining event type. */
|
||||||
if (type == NOTYPE) {
|
if (type == NOTYPE) {
|
||||||
@@ -783,17 +781,6 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
|||||||
log_debug("down at %u,%u", x, y);
|
log_debug("down at %u,%u", x, y);
|
||||||
c->flags |= CLIENT_DOUBLECLICK;
|
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:
|
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. */
|
/* Stop dragging if needed. */
|
||||||
if (type != DRAG &&
|
if (type != DRAG &&
|
||||||
type != WHEEL &&
|
type != WHEEL &&
|
||||||
|
|||||||
5
status.c
5
status.c
@@ -1383,6 +1383,11 @@ process_key:
|
|||||||
break;
|
break;
|
||||||
case KEYC_BSPACE:
|
case KEYC_BSPACE:
|
||||||
case 'h'|KEYC_CTRL:
|
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 != 0) {
|
||||||
if (c->prompt_index == size)
|
if (c->prompt_index == size)
|
||||||
c->prompt_buffer[--c->prompt_index].size = 0;
|
c->prompt_buffer[--c->prompt_index].size = 0;
|
||||||
|
|||||||
6
tmux.1
6
tmux.1
@@ -6718,7 +6718,7 @@ See
|
|||||||
for possible values for
|
for possible values for
|
||||||
.Ar prompt-type .
|
.Ar prompt-type .
|
||||||
.It Xo Ic command-prompt
|
.It Xo Ic command-prompt
|
||||||
.Op Fl 1bFiklN
|
.Op Fl 1beFiklN
|
||||||
.Op Fl I Ar inputs
|
.Op Fl I Ar inputs
|
||||||
.Op Fl p Ar prompts
|
.Op Fl p Ar prompts
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
@@ -6791,6 +6791,10 @@ makes the prompt only accept numeric key presses.
|
|||||||
.Fl i
|
.Fl i
|
||||||
executes the command every time the prompt input changes instead of when the
|
executes the command every time the prompt input changes instead of when the
|
||||||
user exits the command prompt.
|
user exits the command prompt.
|
||||||
|
.Fl e
|
||||||
|
makes
|
||||||
|
.Em BSpace
|
||||||
|
cancel an empty prompt.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl T
|
.Fl T
|
||||||
tells
|
tells
|
||||||
|
|||||||
3
tmux.h
3
tmux.h
@@ -1984,6 +1984,8 @@ struct client {
|
|||||||
struct event repeat_timer;
|
struct event repeat_timer;
|
||||||
|
|
||||||
struct event click_timer;
|
struct event click_timer;
|
||||||
|
int click_where;
|
||||||
|
int click_wp;
|
||||||
u_int click_button;
|
u_int click_button;
|
||||||
struct mouse_event click_event;
|
struct mouse_event click_event;
|
||||||
|
|
||||||
@@ -2094,6 +2096,7 @@ struct client {
|
|||||||
#define PROMPT_KEY 0x10
|
#define PROMPT_KEY 0x10
|
||||||
#define PROMPT_ACCEPT 0x20
|
#define PROMPT_ACCEPT 0x20
|
||||||
#define PROMPT_QUOTENEXT 0x40
|
#define PROMPT_QUOTENEXT 0x40
|
||||||
|
#define PROMPT_BSPACE_EXIT 0x80
|
||||||
int prompt_flags;
|
int prompt_flags;
|
||||||
enum prompt_type prompt_type;
|
enum prompt_type prompt_type;
|
||||||
int prompt_cursor;
|
int prompt_cursor;
|
||||||
|
|||||||
@@ -228,7 +228,6 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
char tim[64], *ptr;
|
char tim[64], *ptr;
|
||||||
const char *timeformat;
|
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
u_int i, j, x, y, idx;
|
u_int i, j, x, y, idx;
|
||||||
@@ -242,20 +241,18 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
|||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
if (style == 0 || style == 2) {
|
if (style == 0 || style == 2) {
|
||||||
if (style == 2)
|
if (style == 2)
|
||||||
timeformat = "%l:%M:%S ";
|
strftime(tim, sizeof tim, "%l:%M:%S ", localtime(&t));
|
||||||
else
|
else
|
||||||
timeformat = "%l:%M ";
|
strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
|
||||||
strftime(tim, sizeof tim, timeformat, localtime(&t));
|
|
||||||
if (tm->tm_hour >= 12)
|
if (tm->tm_hour >= 12)
|
||||||
strlcat(tim, "PM", sizeof tim);
|
strlcat(tim, "PM", sizeof tim);
|
||||||
else
|
else
|
||||||
strlcat(tim, "AM", sizeof tim);
|
strlcat(tim, "AM", sizeof tim);
|
||||||
} else {
|
} else {
|
||||||
if (style == 3)
|
if (style == 3)
|
||||||
timeformat = "%H:%M:%S";
|
strftime(tim, sizeof tim, "%H:%M:%S", tm);
|
||||||
else
|
else
|
||||||
timeformat = "%H:%M";
|
strftime(tim, sizeof tim, "%H:%M", tm);
|
||||||
strftime(tim, sizeof tim, timeformat, tm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_write_clearscreen(&ctx, 8);
|
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);
|
window_pane_reset_mode(wp);
|
||||||
else if (action == WINDOW_COPY_CMD_REDRAW)
|
else if (action == WINDOW_COPY_CMD_REDRAW)
|
||||||
window_copy_redraw_screen(wme);
|
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
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user