diff --git a/CHANGES b/CHANGES index 6ba8968c..932ec115 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +30 November 2007 + +* Support \ek...\e\ to set window name. + 27 November 2007 * Enable/disable mouse when asked, if terminal claims to support it. Mouse @@ -285,4 +289,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.88 2007-11-27 23:28:51 nicm Exp $ +$Id: CHANGES,v 1.89 2007-11-30 11:08:34 nicm Exp $ diff --git a/TODO b/TODO index 3cc55e58..cb2478f6 100644 --- a/TODO +++ b/TODO @@ -58,6 +58,9 @@ - audit copy/scroll and other modes for problems with very small windows - screen_draw_* moved out/renamed (accept TTY_*?) - get rid of stderr/stdout hacks in log.c +- chmod +x socket when any client is attached +- split clients into three RB trees by fd: attached/unattached/dead? + or tailqs? what would be fastest per-char? -- For 0.2 -------------------------------------------------------------------- - window splitting? @@ -65,6 +68,7 @@ - anything which uses cmd_{send,recv}_string will break if the string is split. string length should be part of the command size - echo \\033[35\;46m\\033[2J last line quirk (with C-b r) +- quick intro section (tmux new/attach/detach) etc -------- kmous -- \E[M diff --git a/buffer-poll.c b/buffer-poll.c index 50785e54..099ee4ad 100644 --- a/buffer-poll.c +++ b/buffer-poll.c @@ -1,4 +1,4 @@ -/* $Id: buffer-poll.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ +/* $Id: buffer-poll.c,v 1.4 2007-11-30 11:08:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -24,6 +24,17 @@ #include "tmux.h" +/* Set up pollfd for buffers. */ +void +buffer_set( + struct pollfd *pfd, int fd, unused struct buffer *in, struct buffer *out) +{ + pfd->fd = fd; + pfd->events = POLLIN; + if (BUFFER_USED(out) > 0) + pfd->events |= POLLOUT; +} + /* Fill buffers from socket based on poll results. */ int buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out) @@ -61,8 +72,7 @@ buffer_flush(int fd, struct buffer *in, struct buffer *out) struct pollfd pfd; while (BUFFER_USED(out) > 0) { - pfd.fd = fd; - pfd.events = POLLIN|POLLOUT; + buffer_set(&pfd, fd, in, out); if (poll(&pfd, 1, INFTIM) == -1) { if (errno == EAGAIN || errno == EINTR) diff --git a/input.c b/input.c index 9406a45d..6ac6b54f 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.42 2007-11-27 23:28:51 nicm Exp $ */ +/* $Id: input.c,v 1.43 2007-11-30 11:08:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -38,17 +38,25 @@ int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t); int input_new_argument(struct input_ctx *); int input_add_argument(struct input_ctx *, u_char); -void input_write(struct input_ctx *, int, ...); +void input_start_string(struct input_ctx *, int); +void input_abort_string(struct input_ctx *); +int input_add_string(struct input_ctx *, u_char); +char *input_get_string(struct input_ctx *); -void *input_state_first(u_char, struct input_ctx *); -void *input_state_escape(u_char, struct input_ctx *); -void *input_state_intermediate(u_char, struct input_ctx *); -void *input_state_title_first(u_char, struct input_ctx *); -void *input_state_title_second(u_char, struct input_ctx *); -void *input_state_title_next(u_char, struct input_ctx *); -void *input_state_sequence_first(u_char, struct input_ctx *); -void *input_state_sequence_next(u_char, struct input_ctx *); -void *input_state_sequence_intermediate(u_char, struct input_ctx *); +void input_write(struct input_ctx *, int, ...); +void input_state(struct input_ctx *, void *); + +void input_state_first(u_char, struct input_ctx *); +void input_state_escape(u_char, struct input_ctx *); +void input_state_intermediate(u_char, struct input_ctx *); +void input_state_title_first(u_char, struct input_ctx *); +void input_state_title_second(u_char, struct input_ctx *); +void input_state_title_next(u_char, struct input_ctx *); +void input_state_sequence_first(u_char, struct input_ctx *); +void input_state_sequence_next(u_char, struct input_ctx *); +void input_state_sequence_intermediate(u_char, struct input_ctx *); +void input_state_string_next(u_char, struct input_ctx *); +void input_state_string_escape(u_char, struct input_ctx *); void input_handle_character(u_char, struct input_ctx *); void input_handle_c0_control(u_char, struct input_ctx *); @@ -133,6 +141,48 @@ input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d) return (0); } +void +input_start_string(struct input_ctx *ictx, int type) +{ + ictx->string_type = type; + ictx->string_len = 0; +} + +void +input_abort_string(struct input_ctx *ictx) +{ + xfree(ictx->string_buf); + ictx->string_buf = NULL; +} + +int +input_add_string(struct input_ctx *ictx, u_char ch) +{ + ictx->string_buf = xrealloc(ictx->string_buf, 1, ictx->string_len + 1); + ictx->string_buf[ictx->string_len++] = ch; + + if (ictx->string_len >= MAXSTRINGLEN) { + input_abort_string(ictx); + return (1); + } + + return (0); +} + +char * +input_get_string(struct input_ctx *ictx) +{ + char *s; + + if (ictx->string_buf == NULL) + return (xstrdup("")); + + input_add_string(ictx, '\0'); + s = ictx->string_buf; + ictx->string_buf = NULL; + return (s); +} + void input_write(struct input_ctx *ictx, int cmd, ...) { @@ -146,17 +196,29 @@ input_write(struct input_ctx *ictx, int cmd, ...) va_end(ap); } +void +input_state(struct input_ctx *ictx, void *state) +{ + ictx->state = state; +} + void input_init(struct window *w) { ARRAY_INIT(&w->ictx.args); - w->ictx.state = input_state_first; + w->ictx.string_len = 0; + w->ictx.string_buf = NULL; + + input_state(&w->ictx, input_state_first); } void input_free(struct window *w) { + if (w->ictx.string_buf != NULL) + xfree(w->ictx.string_buf); + ARRAY_FREE(&w->ictx.args); } @@ -179,37 +241,38 @@ input_parse(struct window *w) while (ictx->off < ictx->len) { ch = ictx->buf[ictx->off++]; - ictx->state = ictx->state(ch, ictx); + ictx->state(ch, ictx); } buffer_remove(w->in, ictx->len); } -void * +void input_state_first(u_char ch, struct input_ctx *ictx) { if (INPUT_C0CONTROL(ch)) { if (ch == 0x1b) - return (input_state_escape); - input_handle_c0_control(ch, ictx); - return (input_state_first); + input_state(ictx, input_state_escape); + else + input_handle_c0_control(ch, ictx); + return; } - if (INPUT_C1CONTROL(ch)) { + if (INPUT_C1CONTROL(ch)) { ch -= 0x40; if (ch == '[') - return (input_state_sequence_first); - if (ch == ']') - return (input_state_title_first); - input_handle_c1_control(ch, ictx); - return (input_state_first); + input_state(ictx, input_state_sequence_first); + else if (ch == ']') + input_state(ictx, input_state_title_first); + else + input_handle_c1_control(ch, ictx); + return; } - + input_handle_character(ch, ictx); - return (input_state_first); } -void * +void input_state_escape(u_char ch, struct input_ctx *ictx) { /* Treat C1 control and G1 displayable as 7-bit equivalent. */ @@ -218,164 +281,216 @@ input_state_escape(u_char ch, struct input_ctx *ictx) if (INPUT_C0CONTROL(ch)) { input_handle_c0_control(ch, ictx); - return (input_state_escape); + return; } - if (INPUT_INTERMEDIATE(ch)) - return (input_state_intermediate); + if (INPUT_INTERMEDIATE(ch)) { + input_state(ictx, input_state_intermediate); + return; + } if (INPUT_PARAMETER(ch)) { + input_state(ictx, input_state_first); input_handle_private_two(ch, ictx); - return (input_state_first); + return; } if (INPUT_UPPERCASE(ch)) { if (ch == '[') - return (input_state_sequence_first); - if (ch == ']') - return (input_state_title_first); - input_handle_c1_control(ch, ictx); - return (input_state_first); + input_state(ictx, input_state_sequence_first); + else if (ch == ']') + input_state(ictx, input_state_title_first); + else { + input_state(ictx, input_state_first); + input_handle_c1_control(ch, ictx); + } + return; } if (INPUT_LOWERCASE(ch)) { + input_state(ictx, input_state_first); input_handle_standard_two(ch, ictx); - return (input_state_first); + return; } - return (input_state_first); + input_state(ictx, input_state_first); } -void * +void input_state_title_first(u_char ch, struct input_ctx *ictx) { if (ch >= '0' && ch <= '9') { - ictx->title_type = ch - '0'; - return (input_state_title_second); - } + if (ch == '0') + input_start_string(ictx, STRING_TITLE); + else + input_start_string(ictx, STRING_IGNORE); + input_state(ictx, input_state_title_second); + return; + } - return (input_state_first); + input_state(ictx, input_state_first); } -void * +void input_state_title_second(u_char ch, struct input_ctx *ictx) { if (ch == ';') { - ictx->title_len = 0; - return (input_state_title_next); + input_state(ictx, input_state_title_next); + return; } - return (input_state_first); + input_state(ictx, input_state_first); } -void * +void input_state_title_next(u_char ch, struct input_ctx *ictx) { struct screen *s = &ictx->w->screen; if (ch == '\007') { - ictx->title_buf[ictx->title_len++] = '\0'; - switch (ictx->title_type) { - case 0: - strlcpy(s->title, ictx->title_buf, sizeof s->title); + if (ictx->string_type == STRING_TITLE) { + xfree(s->title); + s->title = input_get_string(ictx); input_write(ictx, TTY_TITLE, s->title); - break; - } - return (input_state_first); + } else + input_abort_string(ictx); + input_state(ictx, input_state_first); + return; } - if (ch >= 0x20) { - if (ictx->title_len < (sizeof ictx->title_buf) - 1) { - ictx->title_buf[ictx->title_len++] = ch; - return (input_state_title_next); - } - return (input_state_first); + if (ch >= 0x20 && ch != 0x7f) { + if (input_add_string(ictx, ch) != 0) + input_state(ictx, input_state_first); + return; } - return (input_state_first); + input_state(ictx, input_state_first); } -void * +void input_state_intermediate(u_char ch, struct input_ctx *ictx) { if (INPUT_INTERMEDIATE(ch)) - return (input_state_intermediate); + return; if (INPUT_PARAMETER(ch)) { + input_state(ictx, input_state_first); input_handle_private_two(ch, ictx); - return (input_state_first); + return; } if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) { + input_state(ictx, input_state_first); input_handle_standard_two(ch, ictx); - return (input_state_first); + return; } - return (input_state_first); + input_state(ictx, input_state_first); } -void * +void input_state_sequence_first(u_char ch, struct input_ctx *ictx) { ictx->private = '\0'; ARRAY_CLEAR(&ictx->args); + input_state(ictx, input_state_sequence_next); + if (INPUT_PARAMETER(ch)) { - input_new_argument(ictx); /* XXX extraneous arg if priv */ + input_new_argument(ictx); if (ch >= 0x3c && ch <= 0x3f) { /* Private control sequence. */ ictx->private = ch; - return (input_state_sequence_next); + return; } - } + } /* Pass character on directly. */ - return (input_state_sequence_next(ch, ictx)); + input_state_sequence_next(ch, ictx); } -void * +void input_state_sequence_next(u_char ch, struct input_ctx *ictx) { if (INPUT_INTERMEDIATE(ch)) { if (input_add_argument(ictx, '\0') != 0) - return (input_state_first); - return (input_state_sequence_intermediate); + input_state(ictx, input_state_first); + else + input_state(ictx, input_state_sequence_intermediate); + return; } if (INPUT_PARAMETER(ch)) { if (ch == ';') { if (input_add_argument(ictx, '\0') != 0) - return (input_state_first); - input_new_argument(ictx); - return (input_state_sequence_next); - } - if (input_add_argument(ictx, ch) != 0) - return (input_state_first); - return (input_state_sequence_next); + input_state(ictx, input_state_first); + else + input_new_argument(ictx); + } else if (input_add_argument(ictx, ch) != 0) + input_state(ictx, input_state_first); + return; } if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) { if (input_add_argument(ictx, '\0') != 0) - return (input_state_first); - input_handle_sequence(ch, ictx); - return (input_state_first); + input_state(ictx, input_state_first); + else { + input_state(ictx, input_state_first); + input_handle_sequence(ch, ictx); + } + return; } - - return (input_state_first); + + input_state(ictx, input_state_first); } -void * +void input_state_sequence_intermediate(u_char ch, struct input_ctx *ictx) { if (INPUT_INTERMEDIATE(ch)) - return (input_state_sequence_intermediate); - + return; + if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) { + input_state(ictx, input_state_first); input_handle_sequence(ch, ictx); - return (input_state_first); + return; + } + + input_state(ictx, input_state_first); +} + +void +input_state_string_next(u_char ch, struct input_ctx *ictx) +{ + if (ch == 0x1b) { + input_state(ictx, input_state_string_escape); + return; } - return (input_state_first); + if (ch >= 0x20 && ch != 0x7f) { + if (input_add_string(ictx, ch) != 0) + input_state(ictx, input_state_first); + return; + } +} + +void +input_state_string_escape(u_char ch, struct input_ctx *ictx) +{ + if (ch == '\\') { + input_state(ictx, input_state_first); + switch (ictx->string_type) { + case STRING_NAME: + xfree(ictx->w->name); + ictx->w->name = input_get_string(ictx); + server_status_window(ictx->w); + break; + } + return; + } + + input_state(ictx, input_state_string_next); + input_state_string_next(ch, ictx); } void @@ -506,7 +621,15 @@ input_handle_standard_two(u_char ch, struct input_ctx *ictx) { log_debug2("-- s2 %zu: %hhu (%c)", ictx->off, ch, ch); - log_debug("unknown s2: %hhu", ch); + switch (ch) { + case 'k': + input_start_string(ictx, STRING_NAME); + input_state(ictx, input_state_string_next); + break; + default: + log_debug("unknown s2: %hhu", ch); + break; + } } void diff --git a/screen.c b/screen.c index 51da4e65..07d007b2 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.53 2007-11-28 08:20:41 nicm Exp $ */ +/* $Id: screen.c,v 1.54 2007-11-30 11:08:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -97,7 +97,7 @@ screen_create(struct screen *s, u_int dx, u_int dy) s->colr = SCREEN_DEFCOLR; s->mode = MODE_CURSOR; - *s->title = '\0'; + s->title = xstrdup(""); s->grid_data = xmalloc(dy * (sizeof *s->grid_data)); s->grid_attr = xmalloc(dy * (sizeof *s->grid_attr)); @@ -260,6 +260,7 @@ screen_set_cell(struct screen *s, void screen_destroy(struct screen *s) { + xfree(s->title); screen_free_lines(s, 0, s->dy + s->hsize); xfree(s->grid_data); xfree(s->grid_attr); diff --git a/tmux.h b/tmux.h index bc11c6a7..031615d0 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.106 2007-11-27 23:28:51 nicm Exp $ */ +/* $Id: tmux.h,v 1.107 2007-11-30 11:08:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -62,8 +62,6 @@ extern char *__progname; #define TTY_NAME_MAX 32 #endif -#define MAXTITLELEN 128 - /* Fatal errors. */ #define fatal(msg) log_fatal("%s: %s", __func__, msg); #define fatalx(msg) log_fatalx("%s: %s", __func__, msg); @@ -355,7 +353,7 @@ struct msg_resize_data { * Each block is y by x in size, row then column order. Sizes are 0-based. */ struct screen { - char title[MAXTITLELEN]; + char *title; u_char **grid_data; u_char **grid_attr; @@ -447,9 +445,13 @@ struct input_ctx { size_t len; size_t off; - u_char title_buf[MAXTITLELEN]; - size_t title_len; - u_int title_type; +#define MAXSTRINGLEN 1024 + u_char *string_buf; + size_t string_len; + int string_type; +#define STRING_TITLE 0 +#define STRING_NAME 1 +#define STRING_IGNORE 2 void *(*state)(u_char, struct input_ctx *); @@ -938,6 +940,8 @@ uint8_t buffer_read8(struct buffer *); uint16_t buffer_read16(struct buffer *); /* buffer-poll.c */ +void buffer_set( + struct pollfd *, int, struct buffer *, struct buffer *); int buffer_poll(struct pollfd *, struct buffer *, struct buffer *); void buffer_flush(int, struct buffer *n, struct buffer *);