summaryrefslogtreecommitdiffstats
path: root/server-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'server-client.c')
-rw-r--r--server-client.c156
1 files changed, 140 insertions, 16 deletions
diff --git a/server-client.c b/server-client.c
index 8144bcd..a749450 100644
--- a/server-client.c
+++ b/server-client.c
@@ -42,6 +42,7 @@ static void server_client_check_modes(struct client *);
static void server_client_set_title(struct client *);
static void server_client_set_path(struct client *);
static void server_client_reset_state(struct client *);
+static int server_client_is_bracket_pasting(struct client *, key_code);
static int server_client_assume_paste(struct session *);
static void server_client_update_latest(struct client *);
@@ -559,9 +560,9 @@ static key_code
server_client_check_mouse(struct client *c, struct key_event *event)
{
struct mouse_event *m = &event->m;
- struct session *s = c->session;
- struct winlink *wl;
- struct window_pane *wp;
+ struct session *s = c->session, *fs;
+ struct winlink *fwl;
+ struct window_pane *wp, *fwp;
u_int x, y, b, sx, sy, px, py;
int ignore = 0;
key_code key;
@@ -667,6 +668,7 @@ have_event:
/* Save the session. */
m->s = s->id;
m->w = -1;
+ m->wp = -1;
m->ignore = ignore;
/* Is this on the status line? */
@@ -683,18 +685,42 @@ have_event:
case STYLE_RANGE_NONE:
return (KEYC_UNKNOWN);
case STYLE_RANGE_LEFT:
+ log_debug("mouse range: left");
where = STATUS_LEFT;
break;
case STYLE_RANGE_RIGHT:
+ log_debug("mouse range: right");
where = STATUS_RIGHT;
break;
+ case STYLE_RANGE_PANE:
+ fwp = window_pane_find_by_id(sr->argument);
+ if (fwp == NULL)
+ return (KEYC_UNKNOWN);
+ m->wp = sr->argument;
+
+ log_debug("mouse range: pane %%%u", m->wp);
+ where = STATUS;
+ break;
case STYLE_RANGE_WINDOW:
- wl = winlink_find_by_index(&s->windows,
+ fwl = winlink_find_by_index(&s->windows,
sr->argument);
- if (wl == NULL)
+ if (fwl == NULL)
return (KEYC_UNKNOWN);
- m->w = wl->window->id;
+ m->w = fwl->window->id;
+ log_debug("mouse range: window @%u", m->w);
+ where = STATUS;
+ break;
+ case STYLE_RANGE_SESSION:
+ fs = session_find_by_id(sr->argument);
+ if (fs == NULL)
+ return (KEYC_UNKNOWN);
+ m->s = sr->argument;
+
+ log_debug("mouse range: session $%u", m->s);
+ where = STATUS;
+ break;
+ case STYLE_RANGE_USER:
where = STATUS;
break;
}
@@ -1754,6 +1780,25 @@ out:
return (key);
}
+/* Is this a bracket paste key? */
+static int
+server_client_is_bracket_pasting(struct client *c, key_code key)
+{
+ if (key == KEYC_PASTE_START) {
+ c->flags |= CLIENT_BRACKETPASTING;
+ log_debug("%s: bracket paste on", c->name);
+ return (1);
+ }
+
+ if (key == KEYC_PASTE_END) {
+ c->flags &= ~CLIENT_BRACKETPASTING;
+ log_debug("%s: bracket paste off", c->name);
+ return (1);
+ }
+
+ return !!(c->flags & CLIENT_BRACKETPASTING);
+}
+
/* Is this fast enough to probably be a paste? */
static int
server_client_assume_paste(struct session *s)
@@ -1818,7 +1863,7 @@ server_client_key_callback(struct cmdq_item *item, void *data)
struct key_binding *bd;
int xtimeout, flags;
struct cmd_find_state fs;
- key_code key0;
+ key_code key0, prefix, prefix2;
/* Check the client is good to accept input. */
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
@@ -1862,8 +1907,14 @@ server_client_key_callback(struct cmdq_item *item, void *data)
if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
goto forward_key;
+ /* Forward if bracket pasting. */
+ if (server_client_is_bracket_pasting(c, key))
+ goto forward_key;
+
/* Treat everything as a regular key when pasting is detected. */
- if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
+ if (!KEYC_IS_MOUSE(key) &&
+ (~key & KEYC_SENT) &&
+ server_client_assume_paste(s))
goto forward_key;
/*
@@ -1884,9 +1935,11 @@ table_changed:
* The prefix always takes precedence and forces a switch to the prefix
* table, unless we are already there.
*/
+ prefix = (key_code)options_get_number(s->options, "prefix");
+ prefix2 = (key_code)options_get_number(s->options, "prefix2");
key0 = (key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS));
- if ((key0 == (key_code)options_get_number(s->options, "prefix") ||
- key0 == (key_code)options_get_number(s->options, "prefix2")) &&
+ if ((key0 == (prefix & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) ||
+ key0 == (prefix2 & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS))) &&
strcmp(table->name, "prefix") != 0) {
server_client_set_key_table(c, "prefix");
server_status_client(c);
@@ -2218,7 +2271,8 @@ server_client_check_pane_buffer(struct window_pane *wp)
}
wpo = control_pane_offset(c, wp, &flag);
if (wpo == NULL) {
- off = 0;
+ if (!flag)
+ off = 0;
continue;
}
if (!flag)
@@ -2714,6 +2768,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
break;
server_client_update_latest(c);
tty_resize(&c->tty);
+ tty_repeat_requests(&c->tty);
recalculate_sizes();
if (c->overlay_resize == NULL)
server_client_clear_overlay(c);
@@ -2788,8 +2843,11 @@ server_client_command_done(struct cmdq_item *item, __unused void *data)
if (~c->flags & CLIENT_ATTACHED)
c->flags |= CLIENT_EXIT;
- else if (~c->flags & CLIENT_EXIT)
+ else if (~c->flags & CLIENT_EXIT) {
+ if (c->flags & CLIENT_CONTROL)
+ control_ready(c);
tty_send_requests(&c->tty);
+ }
return (CMD_RETURN_NORMAL);
}
@@ -2940,14 +2998,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
case MSG_IDENTIFY_STDIN:
if (datalen != 0)
fatalx("bad MSG_IDENTIFY_STDIN size");
- c->fd = imsg->fd;
- log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd);
+ c->fd = imsg_get_fd(imsg);
+ log_debug("client %p IDENTIFY_STDIN %d", c, c->fd);
break;
case MSG_IDENTIFY_STDOUT:
if (datalen != 0)
fatalx("bad MSG_IDENTIFY_STDOUT size");
- c->out_fd = imsg->fd;
- log_debug("client %p IDENTIFY_STDOUT %d", c, imsg->fd);
+ c->out_fd = imsg_get_fd(imsg);
+ log_debug("client %p IDENTIFY_STDOUT %d", c, c->out_fd);
break;
case MSG_IDENTIFY_ENVIRON:
if (datalen == 0 || data[datalen - 1] != '\0')
@@ -3210,3 +3268,69 @@ server_client_remove_pane(struct window_pane *wp)
}
}
}
+
+/* Print to a client. */
+void
+server_client_print(struct client *c, int parse, struct evbuffer *evb)
+{
+ void *data = EVBUFFER_DATA(evb);
+ size_t size = EVBUFFER_LENGTH(evb);
+ struct window_pane *wp;
+ struct window_mode_entry *wme;
+ char *sanitized, *msg, *line;
+
+ if (!parse) {
+ utf8_stravisx(&msg, data, size,
+ VIS_OCTAL|VIS_CSTYLE|VIS_NOSLASH);
+ log_debug("%s: %s", __func__, msg);
+ } else {
+ msg = EVBUFFER_DATA(evb);
+ if (msg[size - 1] != '\0')
+ evbuffer_add(evb, "", 1);
+ }
+
+ if (c == NULL)
+ goto out;
+
+ if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
+ if (~c->flags & CLIENT_UTF8) {
+ sanitized = utf8_sanitize(msg);
+ if (c->flags & CLIENT_CONTROL)
+ control_write(c, "%s", sanitized);
+ else
+ file_print(c, "%s\n", sanitized);
+ free(sanitized);
+ } else {
+ if (c->flags & CLIENT_CONTROL)
+ control_write(c, "%s", msg);
+ else
+ file_print(c, "%s\n", msg);
+ }
+ goto out;
+ }
+
+ wp = server_client_get_pane(c);
+ wme = TAILQ_FIRST(&wp->modes);
+ if (wme == NULL || wme->mode != &window_view_mode)
+ window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
+ if (parse) {
+ do {
+ line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF);
+ if (line != NULL) {
+ window_copy_add(wp, 1, "%s", line);
+ free(line);
+ }
+ } while (line != NULL);
+
+ size = EVBUFFER_LENGTH(evb);
+ if (size != 0) {
+ line = EVBUFFER_DATA(evb);
+ window_copy_add(wp, 1, "%.*s", (int)size, line);
+ }
+ } else
+ window_copy_add(wp, 0, "%s", msg);
+
+out:
+ if (!parse)
+ free(msg);
+}