diff --git a/server-fn.c b/server-fn.c index 9893d409..526a859d 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.43 2008-06-19 18:27:55 nicm Exp $ */ +/* $Id: server-fn.c,v 1.44 2008-06-19 19:40:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,6 +48,35 @@ server_clear_client_message(struct client *c) c->flags |= CLIENT_STATUS; } +void +server_set_client_prompt( + struct client *c, const char *msg, void (*fn)(void *, char *), void *data) +{ + c->prompt_string = xstrdup(msg); + + c->prompt_buffer = xstrdup(""); + c->prompt_index = 0; + + c->prompt_callback = fn; + c->prompt_data = data; + + c->flags |= CLIENT_STATUS; +} + +void +server_clear_client_prompt(struct client *c) +{ + if (c->prompt_string == NULL) + return; + + xfree(c->prompt_string); + c->prompt_string = NULL; + + xfree(c->prompt_buffer); + + c->flags |= CLIENT_STATUS; +} + void server_write_client( struct client *c, enum hdrtype type, const void *buf, size_t len) diff --git a/server.c b/server.c index b10cf476..a7b94186 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.69 2008-06-19 18:27:55 nicm Exp $ */ +/* $Id: server.c,v 1.70 2008-06-19 19:40:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -357,6 +357,8 @@ server_check_redraw(struct client *c) if (c->flags & CLIENT_STATUS) { if (c->message_string != NULL) status_message_redraw(c); + else if (c->prompt_string != NULL) + status_prompt_redraw(c); else status_redraw(c); } @@ -501,7 +503,7 @@ server_accept_client(int srv_fd) c->prompt_string = NULL; c->prompt_buffer = NULL; - c->prompt_size = 0; + c->prompt_index = 0; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { if (ARRAY_ITEM(&clients, i) == NULL) { @@ -523,6 +525,11 @@ server_handle_client(struct client *c) prefix = options_get_key(&c->session->options, "prefix-key"); while (tty_keys_next(&c->tty, &key) == 0) { server_clear_client_message(c); + if (c->prompt_string != NULL) { + status_prompt_key(c, key); + continue; + } + if (c->flags & CLIENT_PREFIX) { key_bindings_dispatch(key, c); c->flags &= ~CLIENT_PREFIX; diff --git a/status.c b/status.c index 20e3282c..59ca12b0 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.31 2008-06-19 18:27:55 nicm Exp $ */ +/* $Id: status.c,v 1.32 2008-06-19 19:40:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -311,3 +311,131 @@ status_message_redraw(struct client *c) /* Force cursor off. */ tty_write_client(c, TTY_CURSOROFF); } + +/* Draw client prompt on status line of present else on last line. */ +void +status_prompt_redraw(struct client *c) +{ + struct screen_redraw_ctx ctx; + size_t i, xx, yy, left, size, offset; + + if (c->sx == 0 || c->sy == 0) + return; + offset = 0; + + xx = strlen(c->prompt_string) + 1; + if (xx > c->sx) + xx = c->sx; + yy = c->sy - 1; + + screen_redraw_start_client(&ctx, c); + screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88); + + screen_redraw_move_cursor(&ctx, 0, yy); + screen_redraw_write_string(&ctx, "%.*s ", (int) xx, c->prompt_string); + + left = c->sx - xx; + if (left != 0) { + if (c->prompt_index < left) + size = strlen(c->prompt_buffer); + else { + offset = c->prompt_index - left; + if (c->prompt_index == strlen(c->prompt_buffer)) + left--; + size = left; + } + screen_redraw_write_string( + &ctx, "%.*s", (int) left, c->prompt_buffer + offset); + + for (i = xx + size; i < c->sx; i++) + ctx.write(ctx.data, TTY_CHARACTER, ' '); + } + + screen_redraw_stop(&ctx); + + /* Force cursor on. */ + tty_write_client(c, TTY_CURSORMOVE, yy, xx + c->prompt_index - offset); + tty_write_client(c, TTY_CURSORON); +} + +/* Handle keys in prompt. */ +void +status_prompt_key(struct client *c, int key) +{ + size_t size; + + size = strlen(c->prompt_buffer); + switch (key) { + case KEYC_LEFT: + if (c->prompt_index > 0) { + c->prompt_index--; + c->flags |= CLIENT_STATUS; + } + break; + case KEYC_RIGHT: + if (c->prompt_index < size) { + c->prompt_index++; + c->flags |= CLIENT_STATUS; + } + break; + case '\001': /* C-a */ + if (c->prompt_index != 0) { + c->prompt_index = 0; + c->flags |= CLIENT_STATUS; + } + break; + case '\005': /* C-e */ + if (c->prompt_index != size) { + c->prompt_index = size; + c->flags |= CLIENT_STATUS; + } + break; + case '\010': + case '\177': + if (c->prompt_index != 0) { + if (c->prompt_index == size) + c->prompt_buffer[--c->prompt_index] = '\0'; + else { + memmove(c->prompt_buffer + c->prompt_index - 1, + c->prompt_buffer + c->prompt_index, + size + 1 - c->prompt_index); + c->prompt_index--; + } + c->flags |= CLIENT_STATUS; + } + break; + case KEYC_DC: + if (c->prompt_index != size) { + memmove(c->prompt_buffer + c->prompt_index, + c->prompt_buffer + c->prompt_index + 1, + size + 1 - c->prompt_index); + c->flags |= CLIENT_STATUS; + } + break; + case '\r': /* enter */ + c->prompt_callback(c->prompt_data, c->prompt_buffer); + server_clear_client_prompt(c); + break; + case '\e': /* escape */ + c->prompt_callback(c->prompt_data, NULL); + server_clear_client_prompt(c); + break; + default: + if (key < 32) + break; + c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2); + + if (c->prompt_index == size) { + c->prompt_buffer[c->prompt_index++] = key; + c->prompt_buffer[c->prompt_index] = '\0'; + } else { + memmove(c->prompt_buffer + c->prompt_index + 1, + c->prompt_buffer + c->prompt_index, + size + 1 - c->prompt_index); + c->prompt_buffer[c->prompt_index++] = key; + } + + c->flags |= CLIENT_STATUS; + break; + } +} diff --git a/tmux.c b/tmux.c index 07a150da..eb1cb467 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.61 2008-06-18 22:21:51 nicm Exp $ */ +/* $Id: tmux.c,v 1.62 2008-06-19 19:40:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -215,7 +215,7 @@ main(int argc, char **argv) options_set_number(&global_options, "bell-action", BELL_ANY); options_set_number(&global_options, "history-limit", 2000); options_set_key(&global_options, "prefix-key", META); - options_set_string(&global_options, "status-left", ""); + options_set_string(&global_options, "status-left", "%s", ""); /* ugh */ options_set_string( &global_options, "status-right", "%%H:%%M %%d-%%b-%%y"); options_set_number(&global_options, "status-interval", 15); diff --git a/tmux.h b/tmux.h index 83e0f643..620b02e9 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.152 2008-06-19 18:27:55 nicm Exp $ */ +/* $Id: tmux.h,v 1.153 2008-06-19 19:40:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -681,7 +681,9 @@ struct client { char *prompt_string; char *prompt_buffer; - size_t prompt_size; + size_t prompt_index; + void (*prompt_callback)(void *, char *); + void *prompt_data; struct session *session; }; @@ -957,6 +959,9 @@ int server_msg_dispatch(struct client *); /* server-fn.c */ void server_set_client_message(struct client *, const char *); void server_clear_client_message(struct client *); +void server_set_client_prompt( + struct client *, const char *, void (*)(void *, char *), void *); +void server_clear_client_prompt(struct client *); struct session *server_extract_session( struct msg_command_data *, char *, char **); void server_write_client( @@ -974,8 +979,10 @@ void server_status_window(struct window *); void printflike2 server_write_message(struct client *, const char *, ...); /* status.c */ -void status_redraw(struct client *c); -void status_message_redraw(struct client *c); +void status_redraw(struct client *); +void status_message_redraw(struct client *); +void status_prompt_redraw(struct client *); +void status_prompt_key(struct client *, int); /* resize.c */ void recalculate_sizes(void); diff --git a/window-copy.c b/window-copy.c index 8cf3e053..2115f10f 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.18 2008-06-18 22:21:51 nicm Exp $ */ +/* $Id: window-copy.c,v 1.19 2008-06-19 19:40:35 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -180,7 +180,7 @@ window_copy_key(struct window *w, int key) screen_clear_selection(&data->screen); break; case '\027': /* C-w */ - case '\r': /* enter */ + case '\r': /* enter */ window_copy_copy_selection(w); window_reset_mode(w); break;