mirror of
https://github.com/tmux/tmux.git
synced 2025-01-15 05:09:04 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
84ddc72744
2
cfg.c
2
cfg.c
@ -286,8 +286,6 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
|||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
if (cmdlist == NULL)
|
|
||||||
continue;
|
|
||||||
new_item = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
new_item = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
|
18
cmd-find.c
18
cmd-find.c
@ -587,8 +587,6 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
|
|||||||
|
|
||||||
/* Try special characters. */
|
/* Try special characters. */
|
||||||
if (strcmp(pane, "!") == 0) {
|
if (strcmp(pane, "!") == 0) {
|
||||||
if (fs->w->last == NULL)
|
|
||||||
return (-1);
|
|
||||||
fs->wp = fs->w->last;
|
fs->wp = fs->w->last;
|
||||||
if (fs->wp == NULL)
|
if (fs->wp == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -912,16 +910,12 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
|||||||
*/
|
*/
|
||||||
fs->w = wp->window;
|
fs->w = wp->window;
|
||||||
if (cmd_find_best_session_with_window(fs) != 0) {
|
if (cmd_find_best_session_with_window(fs) != 0) {
|
||||||
if (wp != NULL) {
|
/*
|
||||||
/*
|
* The window may have been destroyed but the pane
|
||||||
* The window may have been destroyed but the pane
|
* still on all_window_panes due to something else
|
||||||
* still on all_window_panes due to something else
|
* holding a reference.
|
||||||
* holding a reference.
|
*/
|
||||||
*/
|
goto unknown_pane;
|
||||||
goto unknown_pane;
|
|
||||||
}
|
|
||||||
cmd_find_clear_state(fs, 0);
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
fs->wl = fs->s->curw;
|
fs->wl = fs->s->curw;
|
||||||
fs->w = fs->wl->window;
|
fs->w = fs->wl->window;
|
||||||
|
@ -59,7 +59,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *c = item->client;
|
struct client *c = item->client;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
const char *path, *bufname;
|
const char *path, *bufname;
|
||||||
char *pdata, *new_pdata, *cause, *file;
|
char *pdata = NULL, *new_pdata, *cause;
|
||||||
|
char *file;
|
||||||
size_t psize;
|
size_t psize;
|
||||||
int ch, error;
|
int ch, error;
|
||||||
|
|
||||||
@ -89,8 +90,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
f = fopen(file, "rb");
|
f = fopen(file, "rb");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
cmdq_error(item, "%s: %s", file, strerror(errno));
|
cmdq_error(item, "%s: %s", file, strerror(errno));
|
||||||
free(file);
|
goto error;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata = NULL;
|
pdata = NULL;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
static enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
|
static void cmd_pipe_pane_read_callback(struct bufferevent *, void *);
|
||||||
static void cmd_pipe_pane_write_callback(struct bufferevent *, void *);
|
static void cmd_pipe_pane_write_callback(struct bufferevent *, void *);
|
||||||
static void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
|
static void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
@ -42,8 +43,8 @@ const struct cmd_entry cmd_pipe_pane_entry = {
|
|||||||
.name = "pipe-pane",
|
.name = "pipe-pane",
|
||||||
.alias = "pipep",
|
.alias = "pipep",
|
||||||
|
|
||||||
.args = { "ot:", 0, 1 },
|
.args = { "IOot:", 0, 1 },
|
||||||
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]",
|
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [command]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct session *s = item->target.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->target.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int old_fd, pipe_fd[2], null_fd;
|
int old_fd, pipe_fd[2], null_fd, in, out;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
sigset_t set, oldset;
|
sigset_t set, oldset;
|
||||||
|
|
||||||
@ -90,6 +91,15 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(self->args, 'o') && old_fd != -1)
|
if (args_has(self->args, 'o') && old_fd != -1)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
/* What do we want to do? Neither -I or -O is -O. */
|
||||||
|
if (args_has(self->args, 'I')) {
|
||||||
|
in = 1;
|
||||||
|
out = args_has(self->args, 'O');
|
||||||
|
} else {
|
||||||
|
in = 0;
|
||||||
|
out = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the new pipe. */
|
/* Open the new pipe. */
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) {
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) {
|
||||||
cmdq_error(item, "socketpair error: %s", strerror(errno));
|
cmdq_error(item, "socketpair error: %s", strerror(errno));
|
||||||
@ -118,19 +128,25 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
close(pipe_fd[0]);
|
close(pipe_fd[0]);
|
||||||
|
|
||||||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
|
||||||
_exit(1);
|
|
||||||
if (pipe_fd[1] != STDIN_FILENO)
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
|
|
||||||
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
|
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
|
||||||
if (dup2(null_fd, STDOUT_FILENO) == -1)
|
if (out) {
|
||||||
_exit(1);
|
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
||||||
|
_exit(1);
|
||||||
|
} else {
|
||||||
|
if (dup2(null_fd, STDIN_FILENO) == -1)
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
if (in) {
|
||||||
|
if (dup2(pipe_fd[1], STDOUT_FILENO) == -1)
|
||||||
|
_exit(1);
|
||||||
|
if (pipe_fd[1] != STDOUT_FILENO)
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
} else {
|
||||||
|
if (dup2(null_fd, STDOUT_FILENO) == -1)
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
if (dup2(null_fd, STDERR_FILENO) == -1)
|
if (dup2(null_fd, STDERR_FILENO) == -1)
|
||||||
_exit(1);
|
_exit(1);
|
||||||
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
|
|
||||||
close(null_fd);
|
|
||||||
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
closefrom(STDERR_FILENO + 1);
|
||||||
|
|
||||||
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
|
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
|
||||||
@ -143,24 +159,46 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
wp->pipe_fd = pipe_fd[0];
|
wp->pipe_fd = pipe_fd[0];
|
||||||
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
||||||
|
|
||||||
wp->pipe_event = bufferevent_new(wp->pipe_fd, NULL,
|
|
||||||
cmd_pipe_pane_write_callback, cmd_pipe_pane_error_callback,
|
|
||||||
wp);
|
|
||||||
bufferevent_enable(wp->pipe_event, EV_WRITE);
|
|
||||||
|
|
||||||
setblocking(wp->pipe_fd, 0);
|
setblocking(wp->pipe_fd, 0);
|
||||||
|
wp->pipe_event = bufferevent_new(wp->pipe_fd,
|
||||||
|
cmd_pipe_pane_read_callback,
|
||||||
|
cmd_pipe_pane_write_callback,
|
||||||
|
cmd_pipe_pane_error_callback,
|
||||||
|
wp);
|
||||||
|
if (out)
|
||||||
|
bufferevent_enable(wp->pipe_event, EV_WRITE);
|
||||||
|
if (in)
|
||||||
|
bufferevent_enable(wp->pipe_event, EV_READ);
|
||||||
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_pipe_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = data;
|
||||||
|
struct evbuffer *evb = wp->pipe_event->input;
|
||||||
|
size_t available;
|
||||||
|
|
||||||
|
available = EVBUFFER_LENGTH(evb);
|
||||||
|
log_debug("%%%u pipe read %zu", wp->id, available);
|
||||||
|
|
||||||
|
bufferevent_write(wp->event, EVBUFFER_DATA(evb), available);
|
||||||
|
evbuffer_drain(evb, available);
|
||||||
|
|
||||||
|
if (window_pane_destroy_ready(wp))
|
||||||
|
server_destroy_pane(wp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_pipe_pane_write_callback(__unused struct bufferevent *bufev, void *data)
|
cmd_pipe_pane_write_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = data;
|
struct window_pane *wp = data;
|
||||||
|
|
||||||
log_debug("%%%u pipe empty", wp->id);
|
log_debug("%%%u pipe empty", wp->id);
|
||||||
|
|
||||||
if (window_pane_destroy_ready(wp))
|
if (window_pane_destroy_ready(wp))
|
||||||
server_destroy_pane(wp, 1);
|
server_destroy_pane(wp, 1);
|
||||||
}
|
}
|
||||||
|
122
input.c
122
input.c
@ -85,6 +85,7 @@ struct input_ctx {
|
|||||||
u_int param_list_len;
|
u_int param_list_len;
|
||||||
|
|
||||||
struct utf8_data utf8data;
|
struct utf8_data utf8data;
|
||||||
|
int utf8started;
|
||||||
|
|
||||||
int ch;
|
int ch;
|
||||||
int last;
|
int last;
|
||||||
@ -146,9 +147,7 @@ static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
|
|||||||
static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
|
static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
|
||||||
static void input_csi_dispatch_sgr(struct input_ctx *);
|
static void input_csi_dispatch_sgr(struct input_ctx *);
|
||||||
static int input_dcs_dispatch(struct input_ctx *);
|
static int input_dcs_dispatch(struct input_ctx *);
|
||||||
static int input_utf8_open(struct input_ctx *);
|
static int input_top_bit_set(struct input_ctx *);
|
||||||
static int input_utf8_add(struct input_ctx *);
|
|
||||||
static int input_utf8_close(struct input_ctx *);
|
|
||||||
|
|
||||||
/* Command table comparison function. */
|
/* Command table comparison function. */
|
||||||
static int input_table_compare(const void *, const void *);
|
static int input_table_compare(const void *, const void *);
|
||||||
@ -314,9 +313,6 @@ static const struct input_transition input_state_osc_string_table[];
|
|||||||
static const struct input_transition input_state_apc_string_table[];
|
static const struct input_transition input_state_apc_string_table[];
|
||||||
static const struct input_transition input_state_rename_string_table[];
|
static const struct input_transition input_state_rename_string_table[];
|
||||||
static const struct input_transition input_state_consume_st_table[];
|
static const struct input_transition input_state_consume_st_table[];
|
||||||
static const struct input_transition input_state_utf8_three_table[];
|
|
||||||
static const struct input_transition input_state_utf8_two_table[];
|
|
||||||
static const struct input_transition input_state_utf8_one_table[];
|
|
||||||
|
|
||||||
/* ground state definition. */
|
/* ground state definition. */
|
||||||
static const struct input_state input_state_ground = {
|
static const struct input_state input_state_ground = {
|
||||||
@ -437,27 +433,6 @@ static const struct input_state input_state_consume_st = {
|
|||||||
input_state_consume_st_table
|
input_state_consume_st_table
|
||||||
};
|
};
|
||||||
|
|
||||||
/* utf8_three state definition. */
|
|
||||||
static const struct input_state input_state_utf8_three = {
|
|
||||||
"utf8_three",
|
|
||||||
NULL, NULL,
|
|
||||||
input_state_utf8_three_table
|
|
||||||
};
|
|
||||||
|
|
||||||
/* utf8_two state definition. */
|
|
||||||
static const struct input_state input_state_utf8_two = {
|
|
||||||
"utf8_two",
|
|
||||||
NULL, NULL,
|
|
||||||
input_state_utf8_two_table
|
|
||||||
};
|
|
||||||
|
|
||||||
/* utf8_one state definition. */
|
|
||||||
static const struct input_state input_state_utf8_one = {
|
|
||||||
"utf8_one",
|
|
||||||
NULL, NULL,
|
|
||||||
input_state_utf8_one_table
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ground state table. */
|
/* ground state table. */
|
||||||
static const struct input_transition input_state_ground_table[] = {
|
static const struct input_transition input_state_ground_table[] = {
|
||||||
INPUT_STATE_ANYWHERE,
|
INPUT_STATE_ANYWHERE,
|
||||||
@ -467,11 +442,7 @@ static const struct input_transition input_state_ground_table[] = {
|
|||||||
{ 0x1c, 0x1f, input_c0_dispatch, NULL },
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL },
|
||||||
{ 0x20, 0x7e, input_print, NULL },
|
{ 0x20, 0x7e, input_print, NULL },
|
||||||
{ 0x7f, 0x7f, NULL, NULL },
|
{ 0x7f, 0x7f, NULL, NULL },
|
||||||
{ 0x80, 0xc1, NULL, NULL },
|
{ 0x80, 0xff, input_top_bit_set, NULL },
|
||||||
{ 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
|
|
||||||
{ 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
|
|
||||||
{ 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
|
|
||||||
{ 0xf5, 0xff, NULL, NULL },
|
|
||||||
|
|
||||||
{ -1, -1, NULL, NULL }
|
{ -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
@ -717,39 +688,6 @@ static const struct input_transition input_state_consume_st_table[] = {
|
|||||||
{ -1, -1, NULL, NULL }
|
{ -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* utf8_three state table. */
|
|
||||||
static const struct input_transition input_state_utf8_three_table[] = {
|
|
||||||
/* No INPUT_STATE_ANYWHERE */
|
|
||||||
|
|
||||||
{ 0x00, 0x7f, NULL, &input_state_ground },
|
|
||||||
{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
|
|
||||||
{ 0xc0, 0xff, NULL, &input_state_ground },
|
|
||||||
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* utf8_two state table. */
|
|
||||||
static const struct input_transition input_state_utf8_two_table[] = {
|
|
||||||
/* No INPUT_STATE_ANYWHERE */
|
|
||||||
|
|
||||||
{ 0x00, 0x7f, NULL, &input_state_ground },
|
|
||||||
{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
|
|
||||||
{ 0xc0, 0xff, NULL, &input_state_ground },
|
|
||||||
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* utf8_one state table. */
|
|
||||||
static const struct input_transition input_state_utf8_one_table[] = {
|
|
||||||
/* No INPUT_STATE_ANYWHERE */
|
|
||||||
|
|
||||||
{ 0x00, 0x7f, NULL, &input_state_ground },
|
|
||||||
{ 0x80, 0xbf, input_utf8_close, &input_state_ground },
|
|
||||||
{ 0xc0, 0xff, NULL, &input_state_ground },
|
|
||||||
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Input table compare. */
|
/* Input table compare. */
|
||||||
static int
|
static int
|
||||||
input_table_compare(const void *key, const void *value)
|
input_table_compare(const void *key, const void *value)
|
||||||
@ -1059,6 +997,8 @@ input_print(struct input_ctx *ictx)
|
|||||||
{
|
{
|
||||||
int set;
|
int set;
|
||||||
|
|
||||||
|
ictx->utf8started = 0; /* can't be valid UTF-8 */
|
||||||
|
|
||||||
set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
|
set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
|
||||||
if (set == 1)
|
if (set == 1)
|
||||||
ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
|
ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
|
||||||
@ -1132,6 +1072,8 @@ input_c0_dispatch(struct input_ctx *ictx)
|
|||||||
struct window_pane *wp = ictx->wp;
|
struct window_pane *wp = ictx->wp;
|
||||||
struct screen *s = sctx->s;
|
struct screen *s = sctx->s;
|
||||||
|
|
||||||
|
ictx->utf8started = 0; /* can't be valid UTF-8 */
|
||||||
|
|
||||||
log_debug("%s: '%c'", __func__, ictx->ch);
|
log_debug("%s: '%c'", __func__, ictx->ch);
|
||||||
|
|
||||||
switch (ictx->ch) {
|
switch (ictx->ch) {
|
||||||
@ -2064,48 +2006,30 @@ input_exit_rename(struct input_ctx *ictx)
|
|||||||
|
|
||||||
/* Open UTF-8 character. */
|
/* Open UTF-8 character. */
|
||||||
static int
|
static int
|
||||||
input_utf8_open(struct input_ctx *ictx)
|
input_top_bit_set(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct utf8_data *ud = &ictx->utf8data;
|
struct utf8_data *ud = &ictx->utf8data;
|
||||||
|
|
||||||
if (utf8_open(ud, ictx->ch) != UTF8_MORE)
|
|
||||||
fatalx("UTF-8 open invalid %#x", ictx->ch);
|
|
||||||
|
|
||||||
log_debug("%s %hhu", __func__, ud->size);
|
|
||||||
ictx->last = -1;
|
ictx->last = -1;
|
||||||
|
|
||||||
return (0);
|
if (!ictx->utf8started) {
|
||||||
}
|
if (utf8_open(ud, ictx->ch) != UTF8_MORE)
|
||||||
|
return (0);
|
||||||
/* Append to UTF-8 character. */
|
ictx->utf8started = 1;
|
||||||
static int
|
|
||||||
input_utf8_add(struct input_ctx *ictx)
|
|
||||||
{
|
|
||||||
struct utf8_data *ud = &ictx->utf8data;
|
|
||||||
|
|
||||||
if (utf8_append(ud, ictx->ch) != UTF8_MORE)
|
|
||||||
fatalx("UTF-8 add invalid %#x", ictx->ch);
|
|
||||||
|
|
||||||
log_debug("%s", __func__);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close UTF-8 string. */
|
|
||||||
static int
|
|
||||||
input_utf8_close(struct input_ctx *ictx)
|
|
||||||
{
|
|
||||||
struct utf8_data *ud = &ictx->utf8data;
|
|
||||||
|
|
||||||
if (utf8_append(ud, ictx->ch) != UTF8_DONE) {
|
|
||||||
/*
|
|
||||||
* An error here could be invalid UTF-8 or it could be a
|
|
||||||
* nonprintable character for which we can't get the
|
|
||||||
* width. Drop it.
|
|
||||||
*/
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (utf8_append(ud, ictx->ch)) {
|
||||||
|
case UTF8_MORE:
|
||||||
|
return (0);
|
||||||
|
case UTF8_ERROR:
|
||||||
|
ictx->utf8started = 0;
|
||||||
|
return (0);
|
||||||
|
case UTF8_DONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ictx->utf8started = 0;
|
||||||
|
|
||||||
log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
|
log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
|
||||||
(int)ud->size, ud->data, ud->width);
|
(int)ud->size, ud->data, ud->width);
|
||||||
|
|
||||||
|
19
layout.c
19
layout.c
@ -97,9 +97,24 @@ void
|
|||||||
layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
||||||
{
|
{
|
||||||
struct layout_cell *lcchild;
|
struct layout_cell *lcchild;
|
||||||
|
const char *type;
|
||||||
|
|
||||||
log_debug("%s:%*s%p type %u [parent %p] wp=%p [%u,%u %ux%u]", hdr, n,
|
switch (lc->type) {
|
||||||
" ", lc, lc->type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx,
|
case LAYOUT_LEFTRIGHT:
|
||||||
|
type = "LEFTRIGHT";
|
||||||
|
break;
|
||||||
|
case LAYOUT_TOPBOTTOM:
|
||||||
|
type = "TOPBOTTOM";
|
||||||
|
break;
|
||||||
|
case LAYOUT_WINDOWPANE:
|
||||||
|
type = "WINDOWPANE";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = "UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log_debug("%s:%*s%p type %s [parent %p] wp=%p [%u,%u %ux%u]", hdr, n,
|
||||||
|
" ", lc, type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx,
|
||||||
lc->sy);
|
lc->sy);
|
||||||
switch (lc->type) {
|
switch (lc->type) {
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
|
@ -1297,10 +1297,12 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
||||||
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);
|
||||||
}
|
}
|
||||||
if (gc.data.width > 1)
|
if (gc.data.width > 1)
|
||||||
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
grid_view_set_cell(s->grid, xx, s->cy,
|
||||||
|
&grid_default_cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&gc, &ci->gc, sizeof gc);
|
memcpy(&gc, &ci->gc, sizeof gc);
|
||||||
@ -1333,7 +1335,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
collect = 1;
|
collect = 1;
|
||||||
if (gc->data.width != 1 || gc->data.size != 1)
|
if (gc->data.width != 1 || gc->data.size != 1 || *gc->data.data >= 0x7f)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
else if (gc->attr & GRID_ATTR_CHARSET)
|
else if (gc->attr & GRID_ATTR_CHARSET)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
|
27
tmux.1
27
tmux.1
@ -1804,15 +1804,15 @@ If
|
|||||||
.Fl a
|
.Fl a
|
||||||
is used, move to the next window with an alert.
|
is used, move to the next window with an alert.
|
||||||
.It Xo Ic pipe-pane
|
.It Xo Ic pipe-pane
|
||||||
.Op Fl o
|
.Op Fl IOo
|
||||||
.Op Fl t Ar target-pane
|
.Op Fl t Ar target-pane
|
||||||
.Op Ar shell-command
|
.Op Ar shell-command
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic pipep )
|
.D1 (alias: Ic pipep )
|
||||||
Pipe any output sent by the program in
|
Pipe output sent by the program in
|
||||||
.Ar target-pane
|
.Ar target-pane
|
||||||
to a shell command.
|
to a shell command or vice versa.
|
||||||
A pane may only be piped to one command at a time, any existing pipe is
|
A pane may only be connected to one command at a time, any existing pipe is
|
||||||
closed before
|
closed before
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
is executed.
|
is executed.
|
||||||
@ -1825,6 +1825,25 @@ If no
|
|||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
is given, the current pipe (if any) is closed.
|
is given, the current pipe (if any) is closed.
|
||||||
.Pp
|
.Pp
|
||||||
|
.Fl I
|
||||||
|
and
|
||||||
|
.Fl O
|
||||||
|
specify which of the
|
||||||
|
.Ar shell-command
|
||||||
|
output streams are connected to the pane:
|
||||||
|
with
|
||||||
|
.Fl I
|
||||||
|
stdout is connected (so anything
|
||||||
|
.Ar shell-command
|
||||||
|
prints is written to the pane as if it were typed);
|
||||||
|
with
|
||||||
|
.Fl O
|
||||||
|
stdin is connected (so any output in the pane is piped to
|
||||||
|
.Ar shell-command ) .
|
||||||
|
Both may be used together and if neither are specified,
|
||||||
|
.Fl O
|
||||||
|
is used.
|
||||||
|
.Pp
|
||||||
The
|
The
|
||||||
.Fl o
|
.Fl o
|
||||||
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
||||||
|
36
tmux.c
36
tmux.c
@ -44,7 +44,7 @@ int ptm_fd = -1;
|
|||||||
const char *shell_command;
|
const char *shell_command;
|
||||||
|
|
||||||
static __dead void usage(void);
|
static __dead void usage(void);
|
||||||
static char *make_label(const char *);
|
static char *make_label(const char *, char **);
|
||||||
|
|
||||||
static const char *getshell(void);
|
static const char *getshell(void);
|
||||||
static int checkshell(const char *);
|
static int checkshell(const char *);
|
||||||
@ -106,12 +106,13 @@ areshell(const char *shell)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
make_label(const char *label)
|
make_label(const char *label, char **cause)
|
||||||
{
|
{
|
||||||
char *base, resolved[PATH_MAX], *path, *s;
|
char *base, resolved[PATH_MAX], *path, *s;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
int saved_errno;
|
|
||||||
|
*cause = NULL;
|
||||||
|
|
||||||
if (label == NULL)
|
if (label == NULL)
|
||||||
label = "default";
|
label = "default";
|
||||||
@ -121,11 +122,16 @@ make_label(const char *label)
|
|||||||
xasprintf(&base, "%s/tmux-%ld", s, (long)uid);
|
xasprintf(&base, "%s/tmux-%ld", s, (long)uid);
|
||||||
else
|
else
|
||||||
xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid);
|
xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid);
|
||||||
|
if (realpath(base, resolved) == NULL &&
|
||||||
if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
|
strlcpy(resolved, base, sizeof resolved) >= sizeof resolved) {
|
||||||
|
errno = ERANGE;
|
||||||
|
free(base);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (lstat(base, &sb) != 0)
|
if (mkdir(resolved, S_IRWXU) != 0 && errno != EEXIST)
|
||||||
|
goto fail;
|
||||||
|
if (lstat(resolved, &sb) != 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (!S_ISDIR(sb.st_mode)) {
|
if (!S_ISDIR(sb.st_mode)) {
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
@ -135,18 +141,11 @@ make_label(const char *label)
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realpath(base, resolved) == NULL)
|
|
||||||
strlcpy(resolved, base, sizeof resolved);
|
|
||||||
xasprintf(&path, "%s/%s", resolved, label);
|
xasprintf(&path, "%s/%s", resolved, label);
|
||||||
|
|
||||||
free(base);
|
|
||||||
return (path);
|
return (path);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
saved_errno = errno;
|
xasprintf(cause, "error creating %s (%s)", resolved, strerror(errno));
|
||||||
free(base);
|
|
||||||
errno = saved_errno;
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +187,7 @@ find_home(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *path, *label, **var;
|
char *path, *label, *cause, **var;
|
||||||
char tmp[PATH_MAX];
|
char tmp[PATH_MAX];
|
||||||
const char *s, *shell, *cwd;
|
const char *s, *shell, *cwd;
|
||||||
int opt, flags, keys;
|
int opt, flags, keys;
|
||||||
@ -341,8 +340,11 @@ main(int argc, char **argv)
|
|||||||
path[strcspn(path, ",")] = '\0';
|
path[strcspn(path, ",")] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (path == NULL && (path = make_label(label)) == NULL) {
|
if (path == NULL && (path = make_label(label, &cause)) == NULL) {
|
||||||
fprintf(stderr, "can't create socket: %s\n", strerror(errno));
|
if (cause != NULL) {
|
||||||
|
fprintf(stderr, "%s\n", cause);
|
||||||
|
free(cause);
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
socket_path = path;
|
socket_path = path;
|
||||||
|
94
tty.c
94
tty.c
@ -878,12 +878,37 @@ tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox,
|
|||||||
tty_draw_line(tty, wp, wp->screen, py, ox, oy);
|
tty_draw_line(tty, wp, wp->screen, py, ox, oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct grid_cell *
|
||||||
|
tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
static struct grid_cell new;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
/* Characters less than 0x7f are always fine, no matter what. */
|
||||||
|
if (gc->data.size == 1 && *gc->data.data < 0x7f)
|
||||||
|
return (gc);
|
||||||
|
|
||||||
|
/* UTF-8 terminal and a UTF-8 character - fine. */
|
||||||
|
if (tty->flags & TTY_UTF8)
|
||||||
|
return (gc);
|
||||||
|
|
||||||
|
/* Replace by the right number of underscores. */
|
||||||
|
n = gc->data.width;
|
||||||
|
if (n > UTF8_SIZE)
|
||||||
|
n = UTF8_SIZE;
|
||||||
|
memcpy(&new, gc, sizeof new);
|
||||||
|
new.data.size = n;
|
||||||
|
memset(new.data.data, '_', n);
|
||||||
|
return (&new);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
||||||
struct screen *s, u_int py, u_int ox, u_int oy)
|
struct screen *s, u_int py, u_int ox, u_int oy)
|
||||||
{
|
{
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct grid_cell gc, last;
|
struct grid_cell gc, last;
|
||||||
|
const struct grid_cell *gcp;
|
||||||
u_int i, j, ux, sx, nx, width;
|
u_int i, j, ux, sx, nx, width;
|
||||||
int flags, cleared = 0;
|
int flags, cleared = 0;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@ -934,18 +959,15 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
|||||||
|
|
||||||
for (i = 0; i < sx; i++) {
|
for (i = 0; i < sx; i++) {
|
||||||
grid_view_get_cell(gd, i, py, &gc);
|
grid_view_get_cell(gd, i, py, &gc);
|
||||||
|
gcp = tty_check_codeset(tty, &gc);
|
||||||
if (len != 0 &&
|
if (len != 0 &&
|
||||||
(((~tty->flags & TTY_UTF8) &&
|
((gcp->attr & GRID_ATTR_CHARSET) ||
|
||||||
(gc.data.size != 1 ||
|
gcp->flags != last.flags ||
|
||||||
*gc.data.data >= 0x7f ||
|
gcp->attr != last.attr ||
|
||||||
gc.data.width != 1)) ||
|
gcp->fg != last.fg ||
|
||||||
(gc.attr & GRID_ATTR_CHARSET) ||
|
gcp->bg != last.bg ||
|
||||||
gc.flags != last.flags ||
|
ux + width + gcp->data.width >= screen_size_x(s) ||
|
||||||
gc.attr != last.attr ||
|
(sizeof buf) - len < gcp->data.size)) {
|
||||||
gc.fg != last.fg ||
|
|
||||||
gc.bg != last.bg ||
|
|
||||||
ux + width + gc.data.width >= screen_size_x(s) ||
|
|
||||||
(sizeof buf) - len < gc.data.size)) {
|
|
||||||
tty_attributes(tty, &last, wp);
|
tty_attributes(tty, &last, wp);
|
||||||
tty_putn(tty, buf, len, width);
|
tty_putn(tty, buf, len, width);
|
||||||
ux += width;
|
ux += width;
|
||||||
@ -954,35 +976,27 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
|||||||
width = 0;
|
width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gc.flags & GRID_FLAG_SELECTED)
|
if (gcp->flags & GRID_FLAG_SELECTED)
|
||||||
screen_select_cell(s, &last, &gc);
|
screen_select_cell(s, &last, gcp);
|
||||||
else
|
else
|
||||||
memcpy(&last, &gc, sizeof last);
|
memcpy(&last, gcp, sizeof last);
|
||||||
if (ux + gc.data.width > screen_size_x(s))
|
if (ux + gcp->data.width > screen_size_x(s)) {
|
||||||
for (j = 0; j < gc.data.width; j++) {
|
tty_attributes(tty, &last, wp);
|
||||||
|
for (j = 0; j < gcp->data.width; j++) {
|
||||||
if (ux + j > screen_size_x(s))
|
if (ux + j > screen_size_x(s))
|
||||||
break;
|
break;
|
||||||
tty_putc(tty, ' ');
|
tty_putc(tty, ' ');
|
||||||
ux++;
|
ux++;
|
||||||
}
|
}
|
||||||
else if (((~tty->flags & TTY_UTF8) &&
|
} else if (gcp->attr & GRID_ATTR_CHARSET) {
|
||||||
(gc.data.size != 1 ||
|
|
||||||
*gc.data.data >= 0x7f ||
|
|
||||||
gc.data.width != 1)) ||
|
|
||||||
(gc.attr & GRID_ATTR_CHARSET)) {
|
|
||||||
tty_attributes(tty, &last, wp);
|
tty_attributes(tty, &last, wp);
|
||||||
if (~tty->flags & TTY_UTF8) {
|
for (j = 0; j < gcp->data.size; j++)
|
||||||
for (j = 0; j < gc.data.width; j++)
|
tty_putc(tty, gcp->data.data[j]);
|
||||||
tty_putc(tty, '_');
|
|
||||||
} else {
|
|
||||||
for (j = 0; j < gc.data.size; j++)
|
|
||||||
tty_putc(tty, gc.data.data[j]);
|
|
||||||
}
|
|
||||||
ux += gc.data.width;
|
ux += gc.data.width;
|
||||||
} else {
|
} else {
|
||||||
memcpy(buf + len, gc.data.data, gc.data.size);
|
memcpy(buf + len, gcp->data.data, gcp->data.size);
|
||||||
len += gc.data.size;
|
len += gcp->data.size;
|
||||||
width += gc.data.width;
|
width += gcp->data.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
@ -1409,7 +1423,7 @@ static void
|
|||||||
tty_cell(struct tty *tty, const struct grid_cell *gc,
|
tty_cell(struct tty *tty, const struct grid_cell *gc,
|
||||||
const struct window_pane *wp)
|
const struct window_pane *wp)
|
||||||
{
|
{
|
||||||
u_int i;
|
const struct grid_cell *gcp;
|
||||||
|
|
||||||
/* Skip last character if terminal is stupid. */
|
/* Skip last character if terminal is stupid. */
|
||||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||||
@ -1425,22 +1439,16 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
|
|||||||
tty_attributes(tty, gc, wp);
|
tty_attributes(tty, gc, wp);
|
||||||
|
|
||||||
/* Get the cell and if ASCII write with putc to do ACS translation. */
|
/* Get the cell and if ASCII write with putc to do ACS translation. */
|
||||||
if (gc->data.size == 1) {
|
gcp = tty_check_codeset(tty, gc);
|
||||||
if (*gc->data.data < 0x20 || *gc->data.data == 0x7f)
|
if (gcp->data.size == 1) {
|
||||||
|
if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
|
||||||
return;
|
return;
|
||||||
tty_putc(tty, *gc->data.data);
|
tty_putc(tty, *gcp->data.data);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If not UTF-8, write _. */
|
|
||||||
if (!(tty->flags & TTY_UTF8)) {
|
|
||||||
for (i = 0; i < gc->data.width; i++)
|
|
||||||
tty_putc(tty, '_');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the data. */
|
/* Write the data. */
|
||||||
tty_putn(tty, gc->data.data, gc->data.size, gc->data.width);
|
tty_putn(tty, gcp->data.data, gcp->data.size, gcp->data.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user