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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> 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 <n...@users.sourceforge.net> 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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> 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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> 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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 <n...@users.sourceforge.net> @@ -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 $ */ /*