Module Name: src
Committed By: jmmv
Date: Wed Aug 17 18:48:37 UTC 2011
Modified Files:
src/external/bsd/tmux/dist: cmd-paste-buffer.c cmd-server-info.c
cmd-string.c environ.c input.c job.c options.c screen-write.c
screen.c server-fn.c session.c tty-acs.c tty-keys.c tty-term.c
window.c
src/external/bsd/tmux/dist/compat: imsg-buffer.c imsg.c
Removed Files:
src/external/bsd/tmux/dist: cmd-copy-buffer.c cmd-generic.c
cmd-last-pane.c cmd-last-window.c cmd-lock-client.c
cmd-lock-session.c cmd-next-layout.c cmd-next-window.c
cmd-previous-layout.c cmd-previous-window.c cmd-set-window-option.c
cmd-show-window-options.c layout-string.c
Log Message:
Fix merge conflicts after tmux 1.5 import.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r0 src/external/bsd/tmux/dist/cmd-copy-buffer.c
cvs rdiff -u -r1.1.1.1 -r0 src/external/bsd/tmux/dist/cmd-generic.c \
src/external/bsd/tmux/dist/cmd-last-pane.c \
src/external/bsd/tmux/dist/cmd-last-window.c \
src/external/bsd/tmux/dist/cmd-lock-client.c \
src/external/bsd/tmux/dist/cmd-lock-session.c \
src/external/bsd/tmux/dist/cmd-next-layout.c \
src/external/bsd/tmux/dist/cmd-next-window.c \
src/external/bsd/tmux/dist/cmd-previous-layout.c \
src/external/bsd/tmux/dist/cmd-previous-window.c \
src/external/bsd/tmux/dist/cmd-set-window-option.c \
src/external/bsd/tmux/dist/cmd-show-window-options.c \
src/external/bsd/tmux/dist/layout-string.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/tmux/dist/cmd-paste-buffer.c \
src/external/bsd/tmux/dist/cmd-server-info.c \
src/external/bsd/tmux/dist/cmd-string.c \
src/external/bsd/tmux/dist/environ.c src/external/bsd/tmux/dist/input.c \
src/external/bsd/tmux/dist/job.c src/external/bsd/tmux/dist/options.c \
src/external/bsd/tmux/dist/screen-write.c \
src/external/bsd/tmux/dist/screen.c \
src/external/bsd/tmux/dist/server-fn.c \
src/external/bsd/tmux/dist/session.c src/external/bsd/tmux/dist/tty-acs.c \
src/external/bsd/tmux/dist/tty-keys.c \
src/external/bsd/tmux/dist/tty-term.c src/external/bsd/tmux/dist/window.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/tmux/dist/compat/imsg-buffer.c \
src/external/bsd/tmux/dist/compat/imsg.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/bsd/tmux/dist/cmd-paste-buffer.c
diff -u src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.2 src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.3
--- src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.2 Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-paste-buffer.c Wed Aug 17 18:48:35 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-paste-buffer.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-paste-buffer.c,v 1.3 2011/08/17 18:48:35 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -27,131 +27,73 @@
* Paste paste buffer if present.
*/
-struct cmd_paste_buffer_data {
- char *target;
- int buffer;
-
- int flag_delete;
- char *sepstr;
-};
-
-void cmd_paste_buffer_init(struct cmd *, int);
-int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
+
void cmd_paste_buffer_filter(
- struct window_pane *, const char *, size_t, char *);
-void cmd_paste_buffer_free(struct cmd *);
-size_t cmd_paste_buffer_print(struct cmd *, char *, size_t);
+ struct window_pane *, const char *, size_t, const char *);
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
+ "db:rs:t:", 0, 0,
"[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
- 0, "",
- cmd_paste_buffer_init,
- cmd_paste_buffer_parse,
- cmd_paste_buffer_exec,
- cmd_paste_buffer_free,
- cmd_paste_buffer_print
+ 0,
+ NULL,
+ NULL,
+ cmd_paste_buffer_exec
};
-/* ARGSUSED */
-void
-cmd_paste_buffer_init(struct cmd *self, unused int arg)
-{
- struct cmd_paste_buffer_data *data;
-
- self->data = data = xmalloc(sizeof *data);
- data->target = NULL;
- data->buffer = -1;
- data->flag_delete = 0;
- data->sepstr = xstrdup("\r");
-}
-
-int
-cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
-{
- struct cmd_paste_buffer_data *data;
- int opt, n;
- const char *errstr;
-
- cmd_paste_buffer_init(self, 0);
- data = self->data;
-
- while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) {
- switch (opt) {
- case 'b':
- if (data->buffer == -1) {
- n = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL) {
- xasprintf(cause, "buffer %s", errstr);
- goto error;
- }
- data->buffer = n;
- }
- break;
- case 'd':
- data->flag_delete = 1;
- break;
- case 's':
- if (data->sepstr != NULL)
- xfree(data->sepstr);
- data->sepstr = xstrdup(optarg);
- break;
- case 't':
- if (data->target == NULL)
- data->target = xstrdup(optarg);
- break;
- case 'r':
- if (data->sepstr != NULL)
- xfree(data->sepstr);
- data->sepstr = xstrdup("\n");
- break;
- default:
- goto usage;
- }
- }
- argc -= optind;
- argv += optind;
-
- return (0);
-
-usage:
- xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
-
-error:
- self->entry->free(self);
- return (-1);
-}
-
int
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_paste_buffer_data *data = self->data;
- struct window_pane *wp;
- struct session *s;
- struct paste_buffer *pb;
+ struct args *args = self->args;
+ struct window_pane *wp;
+ struct session *s;
+ struct paste_buffer *pb;
+ const char *sepstr;
+ char *cause;
+ int buffer;
- if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
+ if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1);
- if (data->buffer == -1)
- pb = paste_get_top(&s->buffers);
+ if (!args_has(args, 'b'))
+ buffer = -1;
else {
- if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
- ctx->error(ctx, "no buffer %d", data->buffer);
+ buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
+ if (cause != NULL) {
+ ctx->error(ctx, "buffer %s", cause);
+ xfree(cause);
return (-1);
}
}
- if (pb != NULL)
- cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
+ if (buffer == -1)
+ pb = paste_get_top(&global_buffers);
+ else {
+ pb = paste_get_index(&global_buffers, buffer);
+ if (pb == NULL) {
+ ctx->error(ctx, "no buffer %d", buffer);
+ return (-1);
+ }
+ }
+
+ if (pb != NULL) {
+ sepstr = args_get(args, 's');
+ if (sepstr == NULL) {
+ if (args_has(args, 'r'))
+ sepstr = "\n";
+ else
+ sepstr = "\r";
+ }
+ cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr);
+ }
/* Delete the buffer if -d. */
- if (data->flag_delete) {
- if (data->buffer == -1)
- paste_free_top(&s->buffers);
+ if (args_has(args, 'd')) {
+ if (buffer == -1)
+ paste_free_top(&global_buffers);
else
- paste_free_index(&s->buffers, data->buffer);
+ paste_free_index(&global_buffers, buffer);
}
return (0);
@@ -160,7 +102,7 @@
/* Add bytes to a buffer and filter '\n' according to separator. */
void
cmd_paste_buffer_filter(
- struct window_pane *wp, const char *data, size_t size, char *sep)
+ struct window_pane *wp, const char *data, size_t size, const char *sep)
{
const char *end = data + size;
const char *lf;
@@ -177,46 +119,3 @@
if (end != data)
bufferevent_write(wp->event, data, end - data);
}
-
-void
-cmd_paste_buffer_free(struct cmd *self)
-{
- struct cmd_paste_buffer_data *data = self->data;
-
- if (data->target != NULL)
- xfree(data->target);
- if (data->sepstr != NULL)
- xfree(data->sepstr);
- xfree(data);
-}
-
-size_t
-cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
-{
- struct cmd_paste_buffer_data *data = self->data;
- size_t off = 0;
- int r_flag;
-
- r_flag = 0;
- if (data->sepstr != NULL)
- r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
-
- off += xsnprintf(buf, len, "%s", self->entry->name);
- if (data == NULL)
- return (off);
- if (off < len && data->flag_delete)
- off += xsnprintf(buf + off, len - off, " -d");
- if (off < len && r_flag)
- off += xsnprintf(buf + off, len - off, " -r");
- if (off < len && data->buffer != -1)
- off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
- if (off < len && data->sepstr != NULL && !r_flag) {
- size_t slen = strlen(data->sepstr);
- char tmp[slen * 4 + 1];
- strvisx(tmp, data->sepstr, slen, VIS_OCTAL|VIS_TAB|VIS_NL);
- off += cmd_prarg(buf + off, len - off, " -s ", tmp);
- }
- if (off < len && data->target != NULL)
- off += cmd_prarg(buf + off, len - off, " -t ", data->target);
- return (off);
-}
Index: src/external/bsd/tmux/dist/cmd-server-info.c
diff -u src/external/bsd/tmux/dist/cmd-server-info.c:1.2 src/external/bsd/tmux/dist/cmd-server-info.c:1.3
--- src/external/bsd/tmux/dist/cmd-server-info.c:1.2 Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-server-info.c Wed Aug 17 18:48:35 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-server-info.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-server-info.c,v 1.3 2011/08/17 18:48:35 jmmv Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <[email protected]>
@@ -34,44 +34,43 @@
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
+ "", 0, 0,
"",
- 0, "",
+ 0,
NULL,
NULL,
- cmd_server_info_exec,
- NULL,
- NULL
+ cmd_server_info_exec
};
/* ARGSUSED */
int
cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
- struct tty_term *term;
- struct client *c;
- struct session *s;
- struct winlink *wl;
- struct window *w;
- struct window_pane *wp;
- struct tty_code *code;
- struct tty_term_code_entry *ent;
- struct utsname un;
- struct job *job;
- struct grid *gd;
- struct grid_line *gl;
- u_int i, j, k;
- char *tim;
- time_t t;
- u_int lines, ulines;
- size_t size, usize;
+ struct tty_term *term;
+ struct client *c;
+ struct session *s;
+ struct winlink *wl;
+ struct window *w;
+ struct window_pane *wp;
+ struct tty_code *code;
+ const struct tty_term_code_entry *ent;
+ struct utsname un;
+ struct job *job;
+ struct grid *gd;
+ struct grid_line *gl;
+ u_int i, j, k;
+ char *tim;
+ time_t t;
+ u_int lines, ulines;
+ size_t size, usize;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
ctx->print(ctx,
- "tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
+ "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
ctx->print(
ctx, "socket path %s, debug level %d", socket_path, debug_level);
- if (uname(&un) == 0) {
+ if (uname(&un) >= 0) {
ctx->print(ctx, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine);
}
@@ -88,10 +87,11 @@
if (c == NULL || c->session == NULL)
continue;
- ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] "
+ ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho] "
"[flags=0x%x/0x%x, references=%u]", i, c->tty.path,
c->ibuf.fd, c->tty.fd, c->session->name,
- c->tty.sx, c->tty.sy, c->tty.termname, c->flags,
+ c->tty.sx, c->tty.sy, c->tty.termname,
+ c->tty.tio.c_cc[VERASE], c->flags,
c->tty.flags, c->references);
}
ctx->print(ctx, "%s", "");
@@ -141,7 +141,7 @@
ctx->print(ctx, "%s", "");
ctx->print(ctx, "Terminals:");
- SLIST_FOREACH(term, &tty_terms, entry) {
+ LIST_FOREACH(term, &tty_terms, entry) {
ctx->print(ctx, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) {
@@ -176,9 +176,9 @@
ctx->print(ctx, "%s", "");
ctx->print(ctx, "Jobs:");
- SLIST_FOREACH(job, &all_jobs, lentry) {
- ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d, flags=0x%x]",
- job->cmd, job->fd, job->pid, job->status, job->flags);
+ LIST_FOREACH(job, &all_jobs, lentry) {
+ ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d]",
+ job->cmd, job->fd, job->pid, job->status);
}
return (0);
Index: src/external/bsd/tmux/dist/cmd-string.c
diff -u src/external/bsd/tmux/dist/cmd-string.c:1.2 src/external/bsd/tmux/dist/cmd-string.c:1.3
--- src/external/bsd/tmux/dist/cmd-string.c:1.2 Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-string.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-string.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-string.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <[email protected]>
Index: src/external/bsd/tmux/dist/environ.c
diff -u src/external/bsd/tmux/dist/environ.c:1.2 src/external/bsd/tmux/dist/environ.c:1.3
--- src/external/bsd/tmux/dist/environ.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/environ.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: environ.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: environ.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <[email protected]>
Index: src/external/bsd/tmux/dist/input.c
diff -u src/external/bsd/tmux/dist/input.c:1.2 src/external/bsd/tmux/dist/input.c:1.3
--- src/external/bsd/tmux/dist/input.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/input.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: input.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: input.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -41,6 +41,9 @@
*
* - A state for the screen \033k...\033\\ sequence to rename a window. This is
* pretty stupid but not supporting it is more trouble than it is worth.
+ *
+ * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
+ * be passed to the underlying teminal(s).
*/
/* Helper functions. */
@@ -50,8 +53,6 @@
/* Transition entry/exit handlers. */
void input_clear(struct input_ctx *);
-void input_enter_dcs(struct input_ctx *);
-void input_exit_dcs(struct input_ctx *);
void input_enter_osc(struct input_ctx *);
void input_exit_osc(struct input_ctx *);
void input_enter_apc(struct input_ctx *);
@@ -68,6 +69,7 @@
int input_esc_dispatch(struct input_ctx *);
int input_csi_dispatch(struct input_ctx *);
void input_csi_dispatch_sgr(struct input_ctx *);
+int input_dcs_dispatch(struct input_ctx *);
int input_utf8_open(struct input_ctx *);
int input_utf8_add(struct input_ctx *);
int input_utf8_close(struct input_ctx *);
@@ -124,6 +126,7 @@
INPUT_CSI_CUU,
INPUT_CSI_DA,
INPUT_CSI_DCH,
+ INPUT_CSI_DECSCUSR,
INPUT_CSI_DECSTBM,
INPUT_CSI_DL,
INPUT_CSI_DSR,
@@ -166,6 +169,7 @@
{ 'l', "?", INPUT_CSI_RM_PRIVATE },
{ 'm', "", INPUT_CSI_SGR },
{ 'n', "", INPUT_CSI_DSR },
+ { 'q', " ", INPUT_CSI_DECSCUSR },
{ 'r', "", INPUT_CSI_DECSTBM },
};
@@ -204,6 +208,7 @@
const struct input_transition input_state_dcs_parameter_table[];
const struct input_transition input_state_dcs_intermediate_table[];
const struct input_transition input_state_dcs_handler_table[];
+const struct input_transition input_state_dcs_escape_table[];
const struct input_transition input_state_dcs_ignore_table[];
const struct input_transition input_state_osc_string_table[];
const struct input_transition input_state_apc_string_table[];
@@ -286,10 +291,17 @@
/* dcs_handler state definition. */
const struct input_state input_state_dcs_handler = {
"dcs_handler",
- input_enter_dcs, input_exit_dcs,
+ NULL, NULL,
input_state_dcs_handler_table
};
+/* dcs_escape state definition. */
+const struct input_state input_state_dcs_escape = {
+ "dcs_escape",
+ NULL, NULL,
+ input_state_dcs_escape_table
+};
+
/* dcs_ignore state definition. */
const struct input_state input_state_dcs_ignore = {
"dcs_ignore",
@@ -482,7 +494,7 @@
{ 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
{ 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
{ 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
- { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -500,7 +512,7 @@
{ 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
{ 0x3b, 0x3b, input_parameter, NULL },
{ 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
- { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -515,7 +527,7 @@
{ 0x1c, 0x1f, NULL, NULL },
{ 0x20, 0x2f, input_intermediate, NULL },
{ 0x30, 0x3f, NULL, &input_state_dcs_ignore },
- { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -523,18 +535,27 @@
/* dcs_handler state table. */
const struct input_transition input_state_dcs_handler_table[] = {
- INPUT_STATE_ANYWHERE,
+ /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, input_input, NULL },
- { 0x1c, 0x1f, input_input, NULL },
- { 0x20, 0x7e, input_input, NULL },
- { 0x7f, 0xff, NULL, NULL },
+ { 0x00, 0x1a, input_input, NULL },
+ { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
+ { 0x1c, 0xff, input_input, NULL },
+
+ { -1, -1, NULL, NULL }
+};
+
+/* dcs_escape state table. */
+const struct input_transition input_state_dcs_escape_table[] = {
+ /* No INPUT_STATE_ANYWHERE */
+
+ { 0x00, 0x5b, input_input, &input_state_dcs_handler },
+ { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
+ { 0x5d, 0xff, input_input, &input_state_dcs_handler },
{ -1, -1, NULL, NULL }
};
-/* device_ignore state table. */
+/* dcs_ignore state table. */
const struct input_transition input_state_dcs_ignore_table[] = {
INPUT_STATE_ANYWHERE,
@@ -770,7 +791,7 @@
return (0);
}
-/* Get an argument or return default value..*/
+/* Get an argument or return default value. */
int
input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
{
@@ -812,6 +833,9 @@
*ictx->param_buf = '\0';
ictx->param_len = 0;
+ *ictx->input_buf = '\0';
+ ictx->input_len = 0;
+
ictx->flags &= ~INPUT_DISCARD;
}
@@ -953,7 +977,7 @@
screen_write_insertmode(sctx, 0);
screen_write_kcursormode(sctx, 0);
screen_write_kkeypadmode(sctx, 0);
- screen_write_mousemode(sctx, 0);
+ screen_write_mousemode_off(sctx);
screen_write_clearscreen(sctx);
screen_write_cursormove(sctx, 0, 0);
@@ -1156,7 +1180,13 @@
screen_write_cursormode(&ictx->ctx, 0);
break;
case 1000:
- screen_write_mousemode(&ictx->ctx, 0);
+ case 1001:
+ case 1002:
+ case 1003:
+ screen_write_mousemode_off(&ictx->ctx);
+ break;
+ case 1005:
+ screen_write_utf8mousemode(&ictx->ctx, 0);
break;
case 1049:
window_pane_alternate_off(wp, &ictx->cell);
@@ -1192,7 +1222,18 @@
screen_write_cursormode(&ictx->ctx, 1);
break;
case 1000:
- screen_write_mousemode(&ictx->ctx, 1);
+ screen_write_mousemode_on(
+ &ictx->ctx, MODE_MOUSE_STANDARD);
+ break;
+ case 1002:
+ screen_write_mousemode_on(
+ &ictx->ctx, MODE_MOUSE_BUTTON);
+ break;
+ case 1003:
+ screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
+ break;
+ case 1005:
+ screen_write_utf8mousemode(&ictx->ctx, 1);
break;
case 1049:
window_pane_alternate_on(wp, &ictx->cell);
@@ -1220,6 +1261,10 @@
n = input_get(ictx, 0, 1, 1);
screen_write_cursormove(sctx, s->cx, n - 1);
break;
+ case INPUT_CSI_DECSCUSR:
+ n = input_get(ictx, 0, 0, 0);
+ screen_set_cursor_style(s, n);
+ break;
}
return (0);
@@ -1257,7 +1302,7 @@
gc->fg = 8;
} else if (n == 48) {
gc->flags &= ~GRID_FLAG_BG256;
- gc->fg = 8;
+ gc->bg = 8;
}
} else {
@@ -1371,20 +1416,26 @@
}
}
-/* DCS string started. */
-void
-input_enter_dcs(struct input_ctx *ictx)
+/* DCS terminator (ST) received. */
+int
+input_dcs_dispatch(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ const char prefix[] = "tmux;";
+ const u_int prefix_len = (sizeof prefix) - 1;
- ictx->input_len = 0;
-}
+ if (ictx->flags & INPUT_DISCARD)
+ return (0);
-/* DCS terminator (ST) received. */
-void
-input_exit_dcs(unused struct input_ctx *ictx)
-{
- log_debug("%s", __func__);
+ log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+
+ /* Check for tmux prefix. */
+ if (ictx->input_len >= prefix_len &&
+ strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
+ screen_write_rawstring(&ictx->ctx,
+ ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
+ }
+
+ return (0);
}
/* OSC string started. */
@@ -1393,24 +1444,46 @@
{
log_debug("%s", __func__);
- ictx->input_len = 0;
+ input_clear(ictx);
}
/* OSC terminator (ST) received. */
void
input_exit_osc(struct input_ctx *ictx)
{
- if (ictx->flags & INPUT_DISCARD)
- return;
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ u_char *p = ictx->input_buf;
+ int option;
- if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
+ if (ictx->flags & INPUT_DISCARD)
return;
- if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
+ if (ictx->input_len < 1 || *p < '0' || *p > '9')
return;
- screen_set_title(ictx->ctx.s, (const char *)ictx->input_buf + 2);
- server_status_window(ictx->wp->window);
+ log_debug("%s: \"%s\"", __func__, p);
+
+ option = 0;
+ while (*p >= '0' && *p <= '9')
+ option = option * 10 + *p++ - '0';
+ if (*p == ';')
+ p++;
+
+ switch (option) {
+ case 0:
+ case 2:
+ screen_set_title(ictx->ctx.s, p);
+ server_status_window(ictx->wp->window);
+ break;
+ case 12:
+ screen_set_cursor_colour(ictx->ctx.s, p);
+ break;
+ case 112:
+ if (*p == '\0') /* No arguments allowed. */
+ screen_set_cursor_colour(ictx->ctx.s, "");
+ break;
+ default:
+ log_debug("%s: unknown '%u'", __func__, option);
+ break;
+ }
}
/* APC string started. */
@@ -1419,7 +1492,7 @@
{
log_debug("%s", __func__);
- ictx->input_len = 0;
+ input_clear(ictx);
}
/* APC terminator (ST) received. */
@@ -1440,7 +1513,7 @@
{
log_debug("%s", __func__);
- ictx->input_len = 0;
+ input_clear(ictx);
}
/* Rename terminator (ST) received. */
Index: src/external/bsd/tmux/dist/job.c
diff -u src/external/bsd/tmux/dist/job.c:1.2 src/external/bsd/tmux/dist/job.c:1.3
--- src/external/bsd/tmux/dist/job.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/job.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: job.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: job.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <[email protected]>
@@ -30,100 +30,99 @@
* output.
*/
+void job_callback(struct bufferevent *, short, void *);
+
/* All jobs list. */
-struct joblist all_jobs = SLIST_HEAD_INITIALIZER(all_jobs);
+struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
-RB_GENERATE(jobs, job, entry, job_cmp);
+/* Start a job running, if it isn't already. */
+struct job *
+job_run(const char *cmd,
+ void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
+{
+ struct job *job;
+ struct environ env;
+ pid_t pid;
+ int nullfd, out[2];
-void job_callback(struct bufferevent *, short, void *);
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
+ return (NULL);
-int
-job_cmp(struct job *job1, struct job *job2)
-{
- return (strcmp(job1->cmd, job2->cmd));
-}
+ environ_init(&env);
+ environ_copy(&global_environ, &env);
+ server_fill_environ(NULL, &env);
-/* Initialise job tree. */
-void
-job_tree_init(struct jobs *jobs)
-{
- RB_INIT(jobs);
-}
+ switch (pid = fork()) {
+ case -1:
+ environ_free(&env);
+ return (NULL);
+ case 0: /* child */
+ clear_signals(1);
-/* Destroy a job tree. */
-void
-job_tree_free(struct jobs *jobs)
-{
- struct job *job;
+ environ_push(&env);
+ environ_free(&env);
- while (!RB_EMPTY(jobs)) {
- job = RB_ROOT(jobs);
- RB_REMOVE(jobs, jobs, job);
- job_free(job);
- }
-}
+ if (dup2(out[1], STDOUT_FILENO) == -1)
+ fatal("dup2 failed");
+ if (out[1] != STDOUT_FILENO)
+ close(out[1]);
+ close(out[0]);
-/* Find a job and return it. */
-struct job *
-job_get(struct jobs *jobs, const char *cmd)
-{
- struct job job;
+ nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
+ if (nullfd < 0)
+ fatal("open failed");
+ if (dup2(nullfd, STDIN_FILENO) == -1)
+ fatal("dup2 failed");
+ if (dup2(nullfd, STDERR_FILENO) == -1)
+ fatal("dup2 failed");
+ if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
+ close(nullfd);
- job.cmd = __UNCONST(cmd);
- return (RB_FIND(jobs, jobs, &job));
-}
+ closefrom(STDERR_FILENO + 1);
-/* Add a job. */
-struct job *
-job_add(struct jobs *jobs, int flags, struct client *c, const char *cmd,
- void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
-{
- struct job *job;
+ execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
+ fatal("execl failed");
+ }
+
+ /* parent */
+ environ_free(&env);
+ close(out[1]);
job = xmalloc(sizeof *job);
job->cmd = xstrdup(cmd);
- job->pid = -1;
+ job->pid = pid;
job->status = 0;
- job->client = c;
-
- job->fd = -1;
- job->event = NULL;
+ LIST_INSERT_HEAD(&all_jobs, job, lentry);
job->callbackfn = callbackfn;
job->freefn = freefn;
job->data = data;
- job->flags = flags;
+ job->fd = out[0];
+ setblocking(job->fd, 0);
- if (jobs != NULL)
- RB_INSERT(jobs, jobs, job);
- SLIST_INSERT_HEAD(&all_jobs, job, lentry);
+ job->event = bufferevent_new(job->fd, NULL, NULL, job_callback, job);
+ bufferevent_enable(job->event, EV_READ);
+ log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
return (job);
}
-/* Remove job from tree and free. */
-void
-job_remove(struct jobs *jobs, struct job *job)
-{
- if (jobs != NULL)
- RB_REMOVE(jobs, jobs, job);
- job_free(job);
-}
-
/* Kill and free an individual job. */
void
job_free(struct job *job)
{
- job_kill(job);
+ log_debug("free job %p: %s", job, job->cmd);
- SLIST_REMOVE(&all_jobs, job, job, lentry);
+ LIST_REMOVE(job, lentry);
xfree(job->cmd);
if (job->freefn != NULL && job->data != NULL)
job->freefn(job->data);
+ if (job->pid != -1)
+ kill(job->pid, SIGTERM);
if (job->fd != -1)
close(job->fd);
if (job->event != NULL)
@@ -132,65 +131,6 @@
xfree(job);
}
-/* Start a job running, if it isn't already. */
-int
-job_run(struct job *job)
-{
- int nullfd, out[2], mode;
-
- if (job->fd != -1 || job->pid != -1)
- return (0);
-
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
- return (-1);
-
- switch (job->pid = fork()) {
- case -1:
- return (-1);
- case 0: /* child */
- clear_signals(1);
-
- environ_push(&global_environ);
-
- if (dup2(out[1], STDOUT_FILENO) == -1)
- fatal("dup2 failed");
- if (out[1] != STDOUT_FILENO)
- close(out[1]);
- close(out[0]);
-
- nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
- if (nullfd < 0)
- fatal("open failed");
- if (dup2(nullfd, STDIN_FILENO) == -1)
- fatal("dup2 failed");
- if (dup2(nullfd, STDERR_FILENO) == -1)
- fatal("dup2 failed");
- if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
- close(nullfd);
-
- closefrom(STDERR_FILENO + 1);
-
- execl(_PATH_BSHELL, "sh", "-c", job->cmd, (char *) NULL);
- fatal("execl failed");
- default: /* parent */
- close(out[1]);
-
- job->fd = out[0];
- if ((mode = fcntl(job->fd, F_GETFL)) == -1)
- fatal("fcntl failed");
- if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
- fatal("fcntl failed");
-
- if (job->event != NULL)
- bufferevent_free(job->event);
- job->event =
- bufferevent_new(job->fd, NULL, NULL, job_callback, job);
- bufferevent_enable(job->event, EV_READ);
-
- return (0);
- }
-}
-
/* Job buffer error callback. */
/* ARGSUSED */
void
@@ -198,15 +138,16 @@
{
struct job *job = data;
- bufferevent_disable(job->event, EV_READ);
- close(job->fd);
- job->fd = -1;
+ log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
if (job->pid == -1) {
if (job->callbackfn != NULL)
job->callbackfn(job);
- if ((!job->flags & JOB_PERSIST))
- job_free(job);
+ job_free(job);
+ } else {
+ bufferevent_disable(job->event, EV_READ);
+ close(job->fd);
+ job->fd = -1;
}
}
@@ -214,23 +155,14 @@
void
job_died(struct job *job, int status)
{
+ log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid);
+
job->status = status;
- job->pid = -1;
if (job->fd == -1) {
if (job->callbackfn != NULL)
job->callbackfn(job);
- if ((!job->flags & JOB_PERSIST))
- job_free(job);
- }
-}
-
-/* Kill a job. */
-void
-job_kill(struct job *job)
-{
- if (job->pid == -1)
- return;
- kill(job->pid, SIGTERM);
- job->pid = -1;
+ job_free(job);
+ } else
+ job->pid = -1;
}
Index: src/external/bsd/tmux/dist/options.c
diff -u src/external/bsd/tmux/dist/options.c:1.2 src/external/bsd/tmux/dist/options.c:1.3
--- src/external/bsd/tmux/dist/options.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/options.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: options.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: options.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <[email protected]>
Index: src/external/bsd/tmux/dist/screen-write.c
diff -u src/external/bsd/tmux/dist/screen-write.c:1.2 src/external/bsd/tmux/dist/screen-write.c:1.3
--- src/external/bsd/tmux/dist/screen-write.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/screen-write.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: screen-write.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: screen-write.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -830,16 +830,35 @@
s->mode &= ~MODE_INSERT;
}
-/* Set mouse mode. */
+/* Set UTF-8 mouse mode. */
void
-screen_write_mousemode(struct screen_write_ctx *ctx, int state)
+screen_write_utf8mousemode(struct screen_write_ctx *ctx, int state)
{
struct screen *s = ctx->s;
if (state)
- s->mode |= MODE_MOUSE;
+ s->mode |= MODE_MOUSE_UTF8;
else
- s->mode &= ~MODE_MOUSE;
+ s->mode &= ~MODE_MOUSE_UTF8;
+}
+
+/* Set mouse mode off. */
+void
+screen_write_mousemode_off(struct screen_write_ctx *ctx)
+{
+ struct screen *s = ctx->s;
+
+ s->mode &= ~ALL_MOUSE_MODES;
+}
+
+/* Set mouse mode on. */
+void
+screen_write_mousemode_on(struct screen_write_ctx *ctx, int mode)
+{
+ struct screen *s = ctx->s;
+
+ s->mode &= ~ALL_MOUSE_MODES;
+ s->mode |= mode;
}
/* Line feed. */
@@ -913,9 +932,14 @@
sx = screen_size_x(s);
sy = screen_size_y(s);
- if (s->cx <= sx - 1)
- grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
- grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+ /* Scroll into history if it is enabled and clearing entire screen. */
+ if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
+ grid_view_clear_history(s->grid);
+ else {
+ if (s->cx <= sx - 1)
+ grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+ }
tty_write(tty_cmd_clearendofscreen, &ttyctx);
}
@@ -951,7 +975,13 @@
screen_write_initctx(ctx, &ttyctx, 0);
- grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+ /* Scroll into history if it is enabled. */
+ if (s->grid->flags & GRID_HISTORY)
+ grid_view_clear_history(s->grid);
+ else {
+ grid_view_clear(
+ s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+ }
tty_write(tty_cmd_clearscreen, &ttyctx);
}
@@ -983,8 +1013,10 @@
* If this is a wide character and there is no room on the screen, for
* the entire character, don't print it.
*/
- if (width > 1 && (width > screen_size_x(s) ||
- (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
+ if (!(s->mode & MODE_WRAP)
+ && (width > 1 && (width > screen_size_x(s) ||
+ (s->cx != screen_size_x(s)
+ && s->cx > screen_size_x(s) - width))))
return;
/*
@@ -1016,7 +1048,7 @@
}
/* Sanity checks. */
- if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - 1)
+ if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width)
|| s->cy > screen_size_y(s) - 1)
return;
@@ -1162,3 +1194,27 @@
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
}
}
+
+void
+screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+ struct tty_ctx ttyctx;
+
+ screen_write_initctx(ctx, &ttyctx, 0);
+ ttyctx.ptr = str;
+ ttyctx.num = len;
+
+ tty_write(tty_cmd_setselection, &ttyctx);
+}
+
+void
+screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+ struct tty_ctx ttyctx;
+
+ screen_write_initctx(ctx, &ttyctx, 0);
+ ttyctx.ptr = str;
+ ttyctx.num = len;
+
+ tty_write(tty_cmd_rawstring, &ttyctx);
+}
Index: src/external/bsd/tmux/dist/screen.c
diff -u src/external/bsd/tmux/dist/screen.c:1.2 src/external/bsd/tmux/dist/screen.c:1.3
--- src/external/bsd/tmux/dist/screen.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/screen.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: screen.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: screen.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -41,6 +41,8 @@
else
s->title = xstrdup("");
+ s->cstyle = 0;
+ s->ccolour = xstrdup("");
s->tabs = NULL;
screen_reinit(s);
@@ -72,6 +74,7 @@
if (s->tabs != NULL)
xfree(s->tabs);
xfree(s->title);
+ xfree(s->ccolour);
grid_destroy(s->grid);
}
@@ -90,6 +93,22 @@
bit_set(s->tabs, i);
}
+/* Set screen cursor style. */
+void
+screen_set_cursor_style(struct screen *s, u_int style)
+{
+ if (style <= 4)
+ s->cstyle = style;
+}
+
+/* Set screen cursor colour. */
+void
+screen_set_cursor_colour(struct screen *s, const char *colour_string)
+{
+ xfree(s->ccolour);
+ s->ccolour = xstrdup(colour_string);
+}
+
/* Set screen title. */
void
screen_set_title(struct screen *s, const char *title)
Index: src/external/bsd/tmux/dist/server-fn.c
diff -u src/external/bsd/tmux/dist/server-fn.c:1.2 src/external/bsd/tmux/dist/server-fn.c:1.3
--- src/external/bsd/tmux/dist/server-fn.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/server-fn.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: server-fn.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: server-fn.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -30,14 +30,20 @@
void
server_fill_environ(struct session *s, struct environ *env)
{
- char tmuxvar[MAXPATHLEN], *term;
-
- xsnprintf(tmuxvar, sizeof tmuxvar,
- "%s,%ld,%u", socket_path, (long) getpid(), s->idx);
- environ_set(env, "TMUX", tmuxvar);
-
- term = options_get_string(&s->options, "default-terminal");
- environ_set(env, "TERM", term);
+ char var[MAXPATHLEN], *term;
+ u_int idx;
+ long pid;
+
+ if (s != NULL) {
+ term = options_get_string(&s->options, "default-terminal");
+ environ_set(env, "TERM", term);
+
+ idx = s->idx;
+ } else
+ idx = -1;
+ pid = getpid();
+ xsnprintf(var, sizeof var, "%s,%ld,%d", socket_path, pid, idx);
+ environ_set(env, "TMUX", var);
}
void
@@ -396,6 +402,7 @@
} else {
c->last_session = NULL;
c->session = s_new;
+ session_update_activity(s_new);
server_redraw_client(c);
}
}
Index: src/external/bsd/tmux/dist/session.c
diff -u src/external/bsd/tmux/dist/session.c:1.2 src/external/bsd/tmux/dist/session.c:1.3
--- src/external/bsd/tmux/dist/session.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/session.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: session.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: session.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -96,7 +96,7 @@
if (gettimeofday(&s->creation_time, NULL) != 0)
fatal("gettimeofday failed");
- memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
+ session_update_activity(s);
s->cwd = xstrdup(cwd);
@@ -104,8 +104,6 @@
TAILQ_INIT(&s->lastw);
RB_INIT(&s->windows);
- paste_init_stack(&s->buffers);
-
options_init(&s->options, &global_s_options);
environ_init(&s->environ);
if (env != NULL)
@@ -154,7 +152,6 @@
session_group_remove(s);
environ_free(&s->environ);
options_free(&s->options);
- paste_free_stack(&s->buffers);
while (!TAILQ_EMPTY(&s->lastw))
winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
@@ -166,6 +163,21 @@
RB_INSERT(sessions, &dead_sessions, s);
}
+/* Check a session name is valid: not empty and no colons. */
+int
+session_check_name(const char *name)
+{
+ return (*name != '\0' && strchr(name, ':') == NULL);
+}
+
+/* Update session active time. */
+void
+session_update_activity(struct session *s)
+{
+ if (gettimeofday(&s->activity_time, NULL) != 0)
+ fatal("gettimeofday");
+}
+
/* Find the next usable session. */
struct session *
session_next_session(struct session *s)
@@ -175,12 +187,9 @@
if (RB_EMPTY(&sessions) || !session_alive(s))
return (NULL);
- s2 = s;
- do {
- s2 = RB_NEXT(sessions, &sessions, s2);
- if (s2 == NULL)
- s2 = RB_MIN(sessions, &sessions);
- } while (s2 != s);
+ s2 = RB_NEXT(sessions, &sessions, s);
+ if (s2 == NULL)
+ s2 = RB_MIN(sessions, &sessions);
if (s2 == s)
return (NULL);
return (s2);
@@ -195,12 +204,9 @@
if (RB_EMPTY(&sessions) || !session_alive(s))
return (NULL);
- s2 = s;
- do {
- s2 = RB_PREV(sessions, &sessions, s2);
- if (s2 == NULL)
- s2 = RB_MAX(sessions, &sessions);
- } while (s2 != s);
+ s2 = RB_PREV(sessions, &sessions, s);
+ if (s2 == NULL)
+ s2 = RB_MAX(sessions, &sessions);
if (s2 == s)
return (NULL);
return (s2);
@@ -212,10 +218,16 @@
const char *name, const char *cmd, const char *cwd, int idx, char **cause)
{
struct window *w;
+ struct winlink *wl;
struct environ env;
const char *shell;
u_int hlimit;
+ if ((wl = winlink_add(&s->windows, idx)) == NULL) {
+ xasprintf(cause, "index in use: %d", idx);
+ return (NULL);
+ }
+
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
@@ -229,15 +241,18 @@
w = window_create(
name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy, hlimit, cause);
if (w == NULL) {
+ winlink_remove(&s->windows, wl);
environ_free(&env);
return (NULL);
}
+ winlink_set_window(wl, w);
environ_free(&env);
if (options_get_number(&s->options, "set-remain-on-exit"))
options_set_number(&w->options, "remain-on-exit", 1);
- return (session_attach(s, w, idx, cause));
+ session_group_synchronize_from(s);
+ return (wl);
}
/* Attach a window to a session. */
@@ -246,8 +261,12 @@
{
struct winlink *wl;
- if ((wl = winlink_add(&s->windows, w, idx)) == NULL)
+ if ((wl = winlink_add(&s->windows, idx)) == NULL) {
xasprintf(cause, "index in use: %d", idx);
+ return (NULL);
+ }
+ winlink_set_window(wl, w);
+
session_group_synchronize_from(s);
return (wl);
}
@@ -526,7 +545,8 @@
/* Link all the windows from the target. */
RB_FOREACH(wl, winlinks, ww) {
- wl2 = winlink_add(&s->windows, wl->window, wl->idx);
+ wl2 = winlink_add(&s->windows, wl->idx);
+ winlink_set_window(wl2, wl->window);
wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
}
Index: src/external/bsd/tmux/dist/tty-acs.c
diff -u src/external/bsd/tmux/dist/tty-acs.c:1.2 src/external/bsd/tmux/dist/tty-acs.c:1.3
--- src/external/bsd/tmux/dist/tty-acs.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-acs.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-acs.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-acs.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2010 Nicholas Marriott <[email protected]>
Index: src/external/bsd/tmux/dist/tty-keys.c
diff -u src/external/bsd/tmux/dist/tty-keys.c:1.2 src/external/bsd/tmux/dist/tty-keys.c:1.3
--- src/external/bsd/tmux/dist/tty-keys.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-keys.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-keys.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-keys.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -38,7 +38,7 @@
struct tty_key *, const char *, size_t, size_t *);
struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
void tty_keys_callback(int, short, void *);
-int tty_keys_mouse(
+int tty_keys_mouse(struct tty *,
const char *, size_t, size_t *, struct mouse_event *);
struct tty_key_ent {
@@ -54,7 +54,7 @@
* Default key tables. Those flagged with TTYKEY_RAW are inserted directly,
* otherwise they are looked up in terminfo(5).
*/
-struct tty_key_ent tty_keys[] = {
+const struct tty_key_ent tty_keys[] = {
/*
* Numeric keypad. Just use the vt100 escape sequences here and always
* put the terminal into keypad_xmit mode. Translation of numbers
@@ -343,9 +343,9 @@
void
tty_keys_init(struct tty *tty)
{
- struct tty_key_ent *tke;
- u_int i;
- const char *s;
+ const struct tty_key_ent *tke;
+ u_int i;
+ const char *s;
tty->key_tree = NULL;
for (i = 0; i < nitems(tty_keys); i++) {
@@ -462,7 +462,7 @@
}
/* Is this a mouse key press? */
- switch (tty_keys_mouse((const char *)buf, len, &size, &mouse)) {
+ switch (tty_keys_mouse(tty, buf, len, &size, &mouse)) {
case 0: /* yes */
evbuffer_drain(tty->event->input, size);
key = KEYC_MOUSE;
@@ -584,44 +584,74 @@
* (probably a mouse sequence but need more data).
*/
int
-tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
+tty_keys_mouse(struct tty *tty,
+ const char *buf, size_t len, size_t *size, struct mouse_event *m)
{
+ struct utf8_data utf8data;
+ u_int i, value;
+
/*
- * Mouse sequences are \033[M followed by three characters indicating
- * buttons, X and Y, all based at 32 with 1,1 top-left.
+ * Standard mouse sequences are \033[M followed by three characters
+ * indicating buttons, X and Y, all based at 32 with 1,1 top-left.
+ *
+ * UTF-8 mouse sequences are similar but the three are expressed as
+ * UTF-8 characters.
*/
*size = 0;
+ /* First three bytes are always \033[M. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
return (1);
-
if (buf[1] != '[')
return (-1);
if (len == 2)
return (1);
-
if (buf[2] != 'M')
return (-1);
if (len == 3)
return (1);
- if (len < 6)
- return (1);
- *size = 6;
+ /* Read the three inputs. */
+ *size = 3;
+ for (i = 0; i < 3; i++) {
+ if (len < *size)
+ return (1);
+
+ if (tty->mode & MODE_MOUSE_UTF8) {
+ if (utf8_open(&utf8data, buf[*size])) {
+ if (utf8data.size != 2)
+ return (-1);
+ (*size)++;
+ if (len < *size)
+ return (1);
+ utf8_append(&utf8data, buf[*size]);
+ value = utf8_combine(&utf8data);
+ } else
+ value = (unsigned char)buf[*size];
+ (*size)++;
+ } else {
+ value = (unsigned char)buf[*size];
+ (*size)++;
+ }
- log_debug(
- "mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
+ if (i == 0)
+ m->b = value;
+ else if (i == 1)
+ m->x = value;
+ else
+ m->y = value;
+ }
+ log_debug("mouse input: %.*s", (int) *size, buf);
- m->b = buf[3];
- m->x = buf[4];
- m->y = buf[5];
+ /* Check and return the mouse input. */
if (m->b < 32 || m->x < 33 || m->y < 33)
return (-1);
m->b -= 32;
m->x -= 33;
m->y -= 33;
+ log_debug("mouse position: x=%u y=%u b=%u", m->x, m->y, m->b);
return (0);
}
Index: src/external/bsd/tmux/dist/tty-term.c
diff -u src/external/bsd/tmux/dist/tty-term.c:1.2 src/external/bsd/tmux/dist/tty-term.c:1.3
--- src/external/bsd/tmux/dist/tty-term.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-term.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-term.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-term.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <[email protected]>
@@ -18,10 +18,10 @@
#include <sys/types.h>
-#ifdef HAVE_BROKEN_CURSES_H
-#include <ncurses.h>
-#else
+#ifdef HAVE_CURSES_H
#include <curses.h>
+#else
+#include <ncurses.h>
#endif
#include <fnmatch.h>
#include <stdlib.h>
@@ -33,19 +33,23 @@
void tty_term_override(struct tty_term *, const char *);
char *tty_term_strip(const char *);
-struct tty_terms tty_terms = SLIST_HEAD_INITIALIZER(tty_terms);
+struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms);
-struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
+const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_ACSC, TTYCODE_STRING, "acsc" },
{ TTYC_AX, TTYCODE_FLAG, "AX" },
{ TTYC_BEL, TTYCODE_STRING, "bel" },
{ TTYC_BLINK, TTYCODE_STRING, "blink" },
{ TTYC_BOLD, TTYCODE_STRING, "bold" },
+ { TTYC_CC, TTYCODE_STRING, "Cc" },
{ TTYC_CIVIS, TTYCODE_STRING, "civis" },
{ TTYC_CLEAR, TTYCODE_STRING, "clear" },
{ TTYC_CNORM, TTYCODE_STRING, "cnorm" },
{ TTYC_COLORS, TTYCODE_NUMBER, "colors" },
+ { TTYC_CR, TTYCODE_STRING, "Cr" },
+ { TTYC_CS1, TTYCODE_STRING, "Cs" },
{ TTYC_CSR, TTYCODE_STRING, "csr" },
+ { TTYC_CSR1, TTYCODE_STRING, "Csr" },
{ TTYC_CUB, TTYCODE_STRING, "cub" },
{ TTYC_CUB1, TTYCODE_STRING, "cub1" },
{ TTYC_CUD, TTYCODE_STRING, "cud" },
@@ -63,6 +67,7 @@
{ TTYC_EL, TTYCODE_STRING, "el" },
{ TTYC_EL1, TTYCODE_STRING, "el1" },
{ TTYC_ENACS, TTYCODE_STRING, "enacs" },
+ { TTYC_FSL, TTYCODE_STRING, "fsl" },
{ TTYC_HOME, TTYCODE_STRING, "home" },
{ TTYC_HPA, TTYCODE_STRING, "hpa" },
{ TTYC_ICH, TTYCODE_STRING, "ich" },
@@ -165,6 +170,7 @@
{ TTYC_KUP5, TTYCODE_STRING, "kUP5" },
{ TTYC_KUP6, TTYCODE_STRING, "kUP6" },
{ TTYC_KUP7, TTYCODE_STRING, "kUP7" },
+ { TTYC_MS, TTYCODE_STRING, "Ms" },
{ TTYC_OP, TTYCODE_STRING, "op" },
{ TTYC_REV, TTYCODE_STRING, "rev" },
{ TTYC_RI, TTYCODE_STRING, "ri" },
@@ -175,14 +181,17 @@
{ TTYC_SETAB, TTYCODE_STRING, "setab" },
{ TTYC_SETAF, TTYCODE_STRING, "setaf" },
{ TTYC_SGR0, TTYCODE_STRING, "sgr0" },
+ { TTYC_SITM, TTYCODE_STRING, "sitm" },
{ TTYC_SMACS, TTYCODE_STRING, "smacs" },
{ TTYC_SMCUP, TTYCODE_STRING, "smcup" },
{ TTYC_SMIR, TTYCODE_STRING, "smir" },
{ TTYC_SMKX, TTYCODE_STRING, "smkx" },
{ TTYC_SMSO, TTYCODE_STRING, "smso" },
{ TTYC_SMUL, TTYCODE_STRING, "smul" },
+ { TTYC_TSL, TTYCODE_STRING, "tsl" },
{ TTYC_VPA, TTYCODE_STRING, "vpa" },
{ TTYC_XENL, TTYCODE_FLAG, "xenl" },
+ { TTYC_XT, TTYCODE_FLAG, "XT" },
};
char *
@@ -217,13 +226,14 @@
void
tty_term_override(struct tty_term *term, const char *overrides)
{
- struct tty_term_code_entry *ent;
- struct tty_code *code;
- char *termnext, *termstr, *entnext, *entstr;
- char *s, *ptr, *val;
- const char *errstr;
- u_int i;
- int n, removeflag;
+ const struct tty_term_code_entry *ent;
+ struct tty_code *code;
+ char *termnext, *termstr;
+ char *entnext, *entstr;
+ char *s, *ptr, *val;
+ const char *errstr;
+ u_int i;
+ int n, removeflag;
s = xstrdup(overrides);
@@ -253,7 +263,7 @@
entstr[strlen(entstr) - 1] = '\0';
removeflag = 1;
} else
- continue;
+ val = xstrdup("");
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
@@ -299,15 +309,15 @@
struct tty_term *
tty_term_find(char *name, int fd, const char *overrides, char **cause)
{
- struct tty_term *term;
- struct tty_term_code_entry *ent;
- struct tty_code *code;
- u_int i;
- int n, error;
- char *s;
- const char *acs;
+ struct tty_term *term;
+ const struct tty_term_code_entry *ent;
+ struct tty_code *code;
+ u_int i;
+ int n, error;
+ char *s;
+ const char *acs;
- SLIST_FOREACH(term, &tty_terms, entry) {
+ LIST_FOREACH(term, &tty_terms, entry) {
if (strcmp(term->name, name) == 0) {
term->references++;
return (term);
@@ -320,7 +330,7 @@
term->references = 1;
term->flags = 0;
memset(term->codes, 0, sizeof term->codes);
- SLIST_INSERT_HEAD(&tty_terms, term, entry);
+ LIST_INSERT_HEAD(&tty_terms, term, entry);
/* Set up curses terminal. */
if (setupterm(name, fd, &error) != OK) {
@@ -426,6 +436,18 @@
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
term->acs[(u_char) acs[0]][0] = acs[1];
+ /* On terminals with xterm titles (XT), fill in tsl and fsl. */
+ if (tty_term_flag(term, TTYC_XT) &&
+ !tty_term_has(term, TTYC_TSL) &&
+ !tty_term_has(term, TTYC_FSL)) {
+ code = &term->codes[TTYC_TSL];
+ code->value.string = xstrdup("\033]0;");
+ code->type = TTYCODE_STRING;
+ code = &term->codes[TTYC_FSL];
+ code->value.string = xstrdup("\007");
+ code->type = TTYCODE_STRING;
+ }
+
return (term);
error:
@@ -441,7 +463,7 @@
if (--term->references != 0)
return;
- SLIST_REMOVE(&tty_terms, term, tty_term, entry);
+ LIST_REMOVE(term, entry);
for (i = 0; i < NTTYCODE; i++) {
if (term->codes[i].type == TTYCODE_STRING)
@@ -480,6 +502,18 @@
return (tparm(tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
}
+const char *
+tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
+{
+ return (tparm((char *) tty_term_string(term, code), (long)a, 0, 0, 0, 0, 0, 0, 0, 0));
+}
+
+const char *
+tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b)
+{
+ return (tparm((char *) tty_term_string(term, code), (long)a, (long)b, 0, 0, 0, 0, 0, 0, 0));
+}
+
int
tty_term_number(struct tty_term *term, enum tty_code_code code)
{
Index: src/external/bsd/tmux/dist/window.c
diff -u src/external/bsd/tmux/dist/window.c:1.2 src/external/bsd/tmux/dist/window.c:1.3
--- src/external/bsd/tmux/dist/window.c:1.2 Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/window.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: window.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -53,6 +53,10 @@
/* Global window list. */
struct windows windows;
+/* Global panes tree. */
+struct window_pane_tree all_window_panes;
+u_int next_window_pane;
+
void window_pane_read_callback(struct bufferevent *, void *);
void window_pane_error_callback(struct bufferevent *, short, void *);
@@ -64,6 +68,14 @@
return (wl1->idx - wl2->idx);
}
+RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
+
+int
+window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2)
+{
+ return (wp1->id - wp2->id);
+}
+
struct winlink *
winlink_find_by_window(struct winlinks *wwl, struct window *w)
{
@@ -120,7 +132,7 @@
}
struct winlink *
-winlink_add(struct winlinks *wwl, struct window *w, int idx)
+winlink_add(struct winlinks *wwl, int idx)
{
struct winlink *wl;
@@ -132,15 +144,19 @@
wl = xcalloc(1, sizeof *wl);
wl->idx = idx;
- wl->window = w;
RB_INSERT(winlinks, wwl, wl);
- w->references++;
-
return (wl);
}
void
+winlink_set_window(struct winlink *wl, struct window *w)
+{
+ wl->window = w;
+ w->references++;
+}
+
+void
winlink_remove(struct winlinks *wwl, struct winlink *wl)
{
struct window *w = wl->window;
@@ -150,11 +166,13 @@
xfree(wl->status_text);
xfree(wl);
- if (w->references == 0)
- fatal("bad reference count");
- w->references--;
- if (w->references == 0)
- window_destroy(w);
+ if (w != NULL) {
+ if (w->references == 0)
+ fatal("bad reference count");
+ w->references--;
+ if (w->references == 0)
+ window_destroy(w);
+ }
}
struct winlink *
@@ -335,21 +353,65 @@
}
}
-void
-window_set_active_at(struct window *w, u_int x, u_int y)
+struct window_pane *
+window_get_active_at(struct window *w, u_int x, u_int y)
{
struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (wp == w->active || !window_pane_visible(wp))
+ if (!window_pane_visible(wp))
continue;
- if (x < wp->xoff || x >= wp->xoff + wp->sx)
+ if (x < wp->xoff || x > wp->xoff + wp->sx)
continue;
- if (y < wp->yoff || y >= wp->yoff + wp->sy)
+ if (y < wp->yoff || y > wp->yoff + wp->sy)
continue;
- window_set_active_pane(w, wp);
- break;
+ return (wp);
}
+ return (NULL);
+}
+
+void
+window_set_active_at(struct window *w, u_int x, u_int y)
+{
+ struct window_pane *wp;
+
+ wp = window_get_active_at(w, x, y);
+ if (wp != NULL && wp != w->active)
+ window_set_active_pane(w, wp);
+}
+
+struct window_pane *
+window_find_string(struct window *w, const char *s)
+{
+ u_int x, y;
+
+ x = w->sx / 2;
+ y = w->sy / 2;
+
+ if (strcasecmp(s, "top") == 0)
+ y = 0;
+ else if (strcasecmp(s, "bottom") == 0)
+ y = w->sy - 1;
+ else if (strcasecmp(s, "left") == 0)
+ x = 0;
+ else if (strcasecmp(s, "right") == 0)
+ x = w->sx - 1;
+ else if (strcasecmp(s, "top-left") == 0) {
+ x = 0;
+ y = 0;
+ } else if (strcasecmp(s, "top-right") == 0) {
+ x = w->sx - 1;
+ y = 0;
+ } else if (strcasecmp(s, "bottom-left") == 0) {
+ x = 0;
+ y = w->sy - 1;
+ } else if (strcasecmp(s, "bottom-right") == 0) {
+ x = w->sx - 1;
+ y = w->sy - 1;
+ } else
+ return (NULL);
+
+ return (window_get_active_at(w, x, y));
}
struct window_pane *
@@ -460,6 +522,42 @@
}
}
+/* Return list of printable window flag symbols. No flags is just a space. */
+char *
+window_printable_flags(struct session *s, struct winlink *wl)
+{
+ char flags[BUFSIZ];
+ int pos;
+
+ pos = 0;
+ if (wl->flags & WINLINK_ACTIVITY)
+ flags[pos++] = '#';
+ if (wl->flags & WINLINK_BELL)
+ flags[pos++] = '!';
+ if (wl->flags & WINLINK_CONTENT)
+ flags[pos++] = '+';
+ if (wl->flags & WINLINK_SILENCE)
+ flags[pos++] = '~';
+ if (wl == s->curw)
+ flags[pos++] = '*';
+ if (wl == TAILQ_FIRST(&s->lastw))
+ flags[pos++] = '-';
+ if (pos == 0)
+ flags[pos++] = ' ';
+ flags[pos] = '\0';
+ return (xstrdup(flags));
+}
+
+/* Find pane in global tree by id. */
+struct window_pane *
+window_pane_find_by_id(u_int id)
+{
+ struct window_pane wp;
+
+ wp.id = id;
+ return (RB_FIND(window_pane_tree, &all_window_panes, &wp));
+}
+
struct window_pane *
window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
{
@@ -468,6 +566,9 @@
wp = xcalloc(1, sizeof *wp);
wp->window = w;
+ wp->id = next_window_pane++;
+ RB_INSERT(window_pane_tree, &all_window_panes, wp);
+
wp->cmd = NULL;
wp->shell = NULL;
wp->cwd = NULL;
@@ -520,6 +621,8 @@
bufferevent_free(wp->pipe_event);
}
+ RB_REMOVE(window_pane_tree, &all_window_panes, wp);
+
if (wp->cwd != NULL)
xfree(wp->cwd);
if (wp->shell != NULL)
@@ -534,8 +637,7 @@
const char *cwd, struct environ *env, struct termios *tio, char **cause)
{
struct winsize ws;
- int mode;
- char *argv0;
+ char *argv0, paneid[16];
const char *ptr;
struct termios tio2;
@@ -582,6 +684,8 @@
closefrom(STDERR_FILENO + 1);
+ xsnprintf(paneid, sizeof paneid, "%%%u", wp->id);
+ environ_set(env, "TMUX_PANE", paneid);
environ_push(env);
clear_signals(1);
@@ -608,10 +712,8 @@
fatal("execl failed");
}
- if ((mode = fcntl(wp->fd, F_GETFL)) == -1)
- fatal("fcntl failed");
- if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1)
- fatal("fcntl failed");
+ setblocking(wp->fd, 0);
+
wp->event = bufferevent_new(wp->fd,
window_pane_read_callback, NULL, window_pane_error_callback, wp);
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
@@ -832,7 +934,8 @@
m->y -= wp->yoff;
if (wp->mode != NULL) {
- if (wp->mode->mouse != NULL)
+ if (wp->mode->mouse != NULL &&
+ options_get_number(&wp->window->options, "mode-mouse"))
wp->mode->mouse(wp, sess, m);
} else if (wp->fd != -1)
input_mouse(wp, m);
Index: src/external/bsd/tmux/dist/compat/imsg-buffer.c
diff -u src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.2 src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.3
--- src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.2 Mon May 30 16:20:58 2011
+++ src/external/bsd/tmux/dist/compat/imsg-buffer.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: imsg-buffer.c,v 1.2 2011/05/30 16:20:58 joerg Exp $ */
+/* $Id: imsg-buffer.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
/*
Index: src/external/bsd/tmux/dist/compat/imsg.c
diff -u src/external/bsd/tmux/dist/compat/imsg.c:1.2 src/external/bsd/tmux/dist/compat/imsg.c:1.3
--- src/external/bsd/tmux/dist/compat/imsg.c:1.2 Mon May 30 16:20:58 2011
+++ src/external/bsd/tmux/dist/compat/imsg.c Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: imsg.c,v 1.2 2011/05/30 16:20:58 joerg Exp $ */
+/* $Id: imsg.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
/*