From 76c8a590db14131928f79123adcab934a3825501 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2007 19:23:34 +0000 Subject: [PATCH] Big internal reorganisation to move tty control into parent. --- CHANGES | 12 +- Makefile | 7 +- TODO | 17 +- buffer-poll.c | 23 +- buffer.c | 43 ++- client-msg.c | 25 +- client.c | 61 +--- cmd-attach-session.c | 9 +- cmd-copy-mode.c | 4 +- cmd-list-clients.c | 6 +- cmd-new-session.c | 13 +- cmd-scroll-mode.c | 4 +- input-keys.c | 10 +- input.c | 217 ++++-------- key-bindings.c | 4 +- local.c | 793 ------------------------------------------- resize.c | 6 +- screen.c | 155 +++++++-- server-fn.c | 282 +++++---------- server-msg.c | 44 +-- server.c | 77 +++-- status.c | 89 ++--- tmux.h | 208 +++++++----- tty-keys.c | 273 +++++++++++++++ tty-write.c | 107 ++++++ tty.c | 401 ++++++++++++++++++++++ window-copy.c | 275 ++++----------- window-more.c | 136 ++------ window-scroll.c | 176 +++------- window.c | 22 +- 30 files changed, 1577 insertions(+), 1922 deletions(-) delete mode 100644 local.c create mode 100644 tty-keys.c create mode 100644 tty-write.c create mode 100644 tty.c diff --git a/CHANGES b/CHANGES index b7c41ad2..b9ed5a2c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,13 @@ +27 November 2007 + +* Big internal reorganisation. Rather than leaving control of the tty solely in + the client and piping all data through a socket to it, change so that the + server opens the tty again and reads and writes to it directly. This avoids + a lot of buffering and copying.Also reorganise the redrawing stuff so that + everything goes through screen_draw_* - this makes the code simpler, but + still needs broken up more, and all the ways of writing to screens should be + more consistent. + 26 November 2007 * Rather than shifting up one line at a time once the history is full, @@ -273,4 +283,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.86 2007-11-26 22:18:57 nicm Exp $ +$Id: CHANGES,v 1.87 2007-11-27 19:23:32 nicm Exp $ diff --git a/Makefile b/Makefile index 13d72164..1bfe1949 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.48 2007-11-23 17:52:54 nicm Exp $ +# $Id: Makefile,v 1.49 2007-11-27 19:23:33 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -17,7 +17,7 @@ META?= \002 # C-b SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \ - window.c session.c local.c log.c client.c client-msg.c client-fn.c \ + window.c session.c log.c client.c client-msg.c client-fn.c \ key-string.c key-bindings.c resize.c cmd.c cmd-new-session.c \ cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \ cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \ @@ -27,7 +27,8 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-link-window.c cmd-unlink-window.c cmd-next-window.c \ cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \ - cmd-paste-buffer.c window-scroll.c window-more.c window-copy.c + cmd-paste-buffer.c window-scroll.c window-more.c window-copy.c \ + tty.c tty-keys.c tty-write.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index b2221fda..206c4ce8 100644 --- a/TODO +++ b/TODO @@ -1,31 +1,16 @@ -- it would be nice if there wasn't so much copying buffers about, audit uses - useful env vars like WINDOW? -- sort out who controls the buffers in local.c a bit - better checking/emulation for missing term requirements - alt charset, borders etc (terminfo(5)/Line Graphics) - new window command prompt - mouse handling and some other bits elinks needs -- server doesn't handle SIGTERM anymore... -- the whole input/screen/local thing sucks a bit, reorganise/redesign it - line mode/char-at-a-time mode a la telnet? -- some of the uses of buffers really sucks. buffer_reverse_add/remove, - and buffer_insert_range/delete_range are abominations. this should be - rethought - handle ioctl/termios stuff on window sockets - figure out once and for all what is going on with backspace and del backspace should be translated per the termios setting. del passed through? - window creation/idle time -- attributes could be 8 not 16 bits - profile/optimise, particularly (i suspect) input.c -- tidy up input.c a bit - decide about customised status line -- client could pass term/tty fd up to server and then do nothing. what problems - would this cause? -- need access to all terminfo data at once... signals? -- cleanup/redesign IPC - IPC is slightly arse-about-face: overhead? 8-byte header for - each packet... hrm. already scanning output for \e, could add an extra - byte to it for message - could use bsearch all over the place or get rid of smaller tables (clientmsg) - better errors when creating new windows/sessions (how?) - commands should have to care less about CMD_KEY @@ -71,6 +56,8 @@ in $x time (need window creation/use times) - lift SHRT_MAX limits for history - audit copy/scroll and other modes for problems with very small windows +- screen_draw_* moved out/renamed (accept TTY_*?) +- SIGWINCH can probably be handled in server -- For 0.2 -------------------------------------------------------------------- - window splitting? diff --git a/buffer-poll.c b/buffer-poll.c index 06cbf81f..50785e54 100644 --- a/buffer-poll.c +++ b/buffer-poll.c @@ -1,4 +1,4 @@ -/* $Id: buffer-poll.c,v 1.2 2007-11-07 19:41:17 nicm Exp $ */ +/* $Id: buffer-poll.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -53,3 +53,24 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out) } return (0); } + +/* Flush buffer output to socket. */ +void +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; + + if (poll(&pfd, 1, INFTIM) == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; + fatal("poll failed"); + } + + if (buffer_poll(&pfd, in, out) != 0) + break; + } +} diff --git a/buffer.c b/buffer.c index 05ae7084..f5864892 100644 --- a/buffer.c +++ b/buffer.c @@ -1,4 +1,4 @@ -/* $Id: buffer.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ +/* $Id: buffer.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -179,3 +179,44 @@ buffer_read(struct buffer *b, void *data, size_t size) memcpy(data, BUFFER_OUT(b), size); buffer_remove(b, size); } + +/* Store an 8-bit value. */ +void +buffer_write8(struct buffer *b, uint8_t n) +{ + buffer_ensure(b, 1); + BUFFER_IN(b)[0] = n; + buffer_add(b, 1); +} + +/* Store a 16-bit value. */ +void +buffer_write16(struct buffer *b, uint16_t n) +{ + buffer_ensure(b, 2); + BUFFER_IN(b)[0] = n & 0xff; + BUFFER_IN(b)[1] = n >> 8; + buffer_add(b, 2); +} + +/* Extract an 8-bit value. */ +uint8_t +buffer_read8(struct buffer *b) +{ + uint8_t n; + + n = BUFFER_OUT(b)[0]; + buffer_remove(b, 1); + return (n); +} + +/* Extract a 16-bit value. */ +uint16_t +buffer_read16(struct buffer *b) +{ + uint16_t n; + + n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8); + buffer_remove(b, 2); + return (n); +} diff --git a/client-msg.c b/client-msg.c index c334fc48..4e299bc6 100644 --- a/client-msg.c +++ b/client-msg.c @@ -1,4 +1,4 @@ -/* $Id: client-msg.c,v 1.10 2007-10-19 20:50:01 nicm Exp $ */ +/* $Id: client-msg.c,v 1.11 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,7 +25,6 @@ #include "tmux.h" -int client_msg_fn_data(struct hdr *, struct client_ctx *, char **); int client_msg_fn_detach(struct hdr *, struct client_ctx *, char **); int client_msg_fn_error(struct hdr *, struct client_ctx *, char **); int client_msg_fn_exit(struct hdr *, struct client_ctx *, char **); @@ -38,11 +37,9 @@ struct client_msg { int (*fn)(struct hdr *, struct client_ctx *, char **); }; struct client_msg client_msg_table[] = { - { MSG_DATA, client_msg_fn_data }, { MSG_DETACH, client_msg_fn_detach }, { MSG_ERROR, client_msg_fn_error }, { MSG_EXIT, client_msg_fn_exit }, - { MSG_PAUSE, client_msg_fn_pause }, }; #define NCLIENTMSG (sizeof client_msg_table / sizeof client_msg_table[0]) @@ -71,26 +68,6 @@ client_msg_dispatch(struct client_ctx *cctx, char **error) fatalx("unexpected message"); } -int -client_msg_fn_data( - struct hdr *hdr, struct client_ctx *cctx, unused char **error) -{ - local_output(cctx->srv_in, hdr->size); - return (0); -} - -int -client_msg_fn_pause( - struct hdr *hdr, unused struct client_ctx *cctx, unused char **error) -{ - if (hdr->size != 0) - fatalx("bad MSG_PAUSE size"); - - cctx->flags |= CCTX_PAUSE; - - return (0); -} - int client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error) { diff --git a/client.c b/client.c index 1bf97966..b21d49fd 100644 --- a/client.c +++ b/client.c @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.22 2007-11-26 20:36:30 nicm Exp $ */ +/* $Id: client.c,v 1.23 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -33,7 +33,6 @@ #include "tmux.h" void client_handle_winch(struct client_ctx *); -int client_process_local(struct client_ctx *, char **); int client_init(const char *path, struct client_ctx *cctx, int start_server) @@ -113,6 +112,7 @@ retry: if (ttyname_r(STDIN_FILENO, data.tty, sizeof data.tty) != 0) fatal("ttyname_r failed"); client_write_server(cctx, MSG_IDENTIFY, &data, sizeof data); + cmd_send_string(cctx->srv_out, getenv("TERM")); } return (0); @@ -121,13 +121,11 @@ retry: int client_main(struct client_ctx *cctx) { - struct pollfd pfds[2]; + struct pollfd pfd; char *error; int timeout; siginit(); - if ((cctx->loc_fd = local_init(&cctx->loc_in, &cctx->loc_out)) == -1) - return (1); logfile("client"); #ifndef NO_SETPROCTITLE @@ -140,34 +138,20 @@ client_main(struct client_ctx *cctx) if (sigwinch) client_handle_winch(cctx); - pfds[0].fd = cctx->srv_fd; - pfds[0].events = POLLIN; + pfd.fd = cctx->srv_fd; + pfd.events = POLLIN; if (BUFFER_USED(cctx->srv_out) > 0) - pfds[0].events |= POLLOUT; - pfds[1].fd = cctx->loc_fd; - pfds[1].events = POLLIN; - if (BUFFER_USED(cctx->loc_out) > 0) - pfds[1].events |= POLLOUT; + pfd.events |= POLLOUT; - if (poll(pfds, 2, timeout) == -1) { + if (poll(&pfd, 1, timeout) == -1) { if (errno == EAGAIN || errno == EINTR) continue; fatal("poll failed"); } - if (buffer_poll(&pfds[0], cctx->srv_in, cctx->srv_out) != 0) + if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0) goto server_dead; - if (buffer_poll(&pfds[1], cctx->loc_in, cctx->loc_out) != 0) - goto local_dead; - if (cctx->flags & CCTX_PAUSE) { - usleep(750000); - cctx->flags = 0; - } - - if (client_process_local(cctx, &error) == -1) - goto out; - switch (client_msg_dispatch(cctx, &error)) { case -1: goto out; @@ -183,8 +167,6 @@ client_main(struct client_ctx *cctx) } out: - local_done(); - if (sigterm) { printf("[terminated]\n"); return (1); @@ -204,14 +186,8 @@ out: return (1); server_dead: - local_done(); - printf("[lost server]\n"); return (0); - -local_dead: - /* Can't do much here. Log and die. */ - fatalx("local socket dead"); } void @@ -229,24 +205,3 @@ client_handle_winch(struct client_ctx *cctx) sigwinch = 0; } - -int -client_process_local(struct client_ctx *cctx, unused char **error) -{ - struct buffer *b; - int key; - - b = buffer_create(BUFSIZ); - while ((key = local_key()) != KEYC_NONE) - input_store16(b, (uint16_t) key); - - log_debug("transmitting %zu bytes of input", BUFFER_USED(b)); - if (BUFFER_USED(b) != 0) { - client_write_server( - cctx, MSG_KEYS, BUFFER_OUT(b), BUFFER_USED(b)); - } - - buffer_destroy(b); - return (0); -} - diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 621c2bfd..930b756b 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-attach-session.c,v 1.9 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-attach-session.c,v 1.10 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -83,6 +83,7 @@ void cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_attach_session_data *data = ptr; + char *cause; if (ctx->flags & CMD_KEY) return; @@ -92,6 +93,12 @@ cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx) return; } + if (tty_open(&ctx->cmdclient->tty, &cause) != 0) { + ctx->error(ctx, "%s", cause); + xfree(cause); + return; + } + if (data->flag_detach) server_write_session(ctx->session, MSG_DETACH, NULL, 0); ctx->cmdclient->session = ctx->session; diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 9d47ad3f..665507e1 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-copy-mode.c,v 1.1 2007-11-23 14:28:47 nicm Exp $ */ +/* $Id: cmd-copy-mode.c,v 1.2 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -47,7 +47,7 @@ cmd_copy_mode_exec(unused void *ptr, struct cmd_ctx *ctx) if (w->mode == NULL && ctx->flags & CMD_KEY) { w->mode = &window_copy_mode; w->mode->init(w); - server_redraw_window_all(w); + server_redraw_window(w); } if (ctx->cmdclient != NULL) diff --git a/cmd-list-clients.c b/cmd-list-clients.c index 0713e258..54743c42 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-clients.c,v 1.2 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-list-clients.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -51,8 +51,8 @@ cmd_list_clients_exec(unused void *ptr, struct cmd_ctx *ctx) if (c == NULL || c->session == NULL) continue; - ctx->print(ctx, - "%s: %s [%ux%u]", c->tty, c->session->name, c->sx, c->sy); + ctx->print(ctx, "%s: %s [%ux%u]", + c->tty.path, c->session->name, c->sx, c->sy); } if (ctx->cmdclient != NULL) diff --git a/cmd-new-session.c b/cmd-new-session.c index 75574f41..418fbf8e 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-session.c,v 1.17 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-new-session.c,v 1.18 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -100,8 +100,8 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_new_session_data *data = ptr; struct cmd_new_session_data std = { NULL, NULL, NULL, 0 }; - struct client *c; - char *cmd; + struct client *c = ctx->cmdclient; + char *cmd, *cause; u_int sy; if (data == NULL) @@ -110,7 +110,6 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) if (ctx->flags & CMD_KEY) return; - c = ctx->cmdclient; if (!data->flag_detached && !(c->flags & CLIENT_TERMINAL)) { ctx->error(ctx, "not a terminal"); return; @@ -126,6 +125,12 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) sy = status_lines + 1; sy -= status_lines; + if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { + ctx->error(ctx, "%s", cause); + xfree(cause); + return; + } + cmd = data->cmd; if (cmd == NULL) cmd = default_command; diff --git a/cmd-scroll-mode.c b/cmd-scroll-mode.c index 6b7f6abc..17d839ae 100644 --- a/cmd-scroll-mode.c +++ b/cmd-scroll-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-scroll-mode.c,v 1.3 2007-11-22 18:09:43 nicm Exp $ */ +/* $Id: cmd-scroll-mode.c,v 1.4 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -47,7 +47,7 @@ cmd_scroll_mode_exec(unused void *ptr, struct cmd_ctx *ctx) if (w->mode == NULL && ctx->flags & CMD_KEY) { w->mode = &window_scroll_mode; w->mode->init(w); - server_redraw_window_all(w); + server_redraw_window(w); } if (ctx->cmdclient != NULL) diff --git a/input-keys.c b/input-keys.c index 1d11893f..4031d381 100644 --- a/input-keys.c +++ b/input-keys.c @@ -1,4 +1,4 @@ -/* $Id: input-keys.c,v 1.3 2007-11-21 13:11:41 nicm Exp $ */ +/* $Id: input-keys.c,v 1.4 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -55,13 +55,13 @@ struct { /* Translate a key code from client into an output key sequence. */ void -input_key(struct buffer *b, int key) +input_key(struct window *w, int key) { u_int i; log_debug2("writing key %d", key); if (key != KEYC_NONE && key >= 0) { - input_store8(b, key); + buffer_write8(w->out, (uint8_t) key); return; } @@ -69,8 +69,8 @@ input_key(struct buffer *b, int key) if (input_keys[i].key == key) { log_debug2( "found key %d: \"%s\"", key, input_keys[i].data); - buffer_write( - b, input_keys[i].data, strlen(input_keys[i].data)); + buffer_write(w->out, + input_keys[i].data, strlen(input_keys[i].data)); return; } } diff --git a/input.c b/input.c index fee4dd04..4de6964d 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.38 2007-11-24 23:29:49 nicm Exp $ */ +/* $Id: input.c,v 1.39 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -36,7 +36,9 @@ 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 ch); +int input_add_argument(struct input_ctx *, u_char); + +void input_write(struct input_ctx *, int, ...); void *input_state_first(u_char, struct input_ctx *); void *input_state_escape(u_char, struct input_ctx *); @@ -131,6 +133,19 @@ input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d) return (0); } +void +input_write(struct input_ctx *ictx, int cmd, ...) +{ + va_list ap; + + if (ictx->w->screen.mode & (MODE_HIDDEN|MODE_BACKGROUND)) + return; + + va_start(ap, cmd); + tty_vwrite_window(ictx->w, cmd, ap); + va_end(ap); +} + void input_init(struct window *w) { @@ -146,7 +161,7 @@ input_free(struct window *w) } void -input_parse(struct window *w, struct buffer *b) +input_parse(struct window *w) { struct input_ctx *ictx = &w->ictx; u_char ch; @@ -159,7 +174,6 @@ input_parse(struct window *w, struct buffer *b) ictx->off = 0; ictx->w = w; - ictx->b = b; log_debug2("entry; buffer=%zu", ictx->len); @@ -264,8 +278,7 @@ input_state_title_next(u_char ch, struct input_ctx *ictx) switch (ictx->title_type) { case 0: strlcpy(s->title, ictx->title_buf, sizeof s->title); - input_store_one(ictx->b, CODE_TITLE, ictx->title_len); - buffer_write(ictx->b, ictx->title_buf, ictx->title_len); + input_write(ictx, TTY_TITLE, s->title); break; } return (input_state_first); @@ -373,10 +386,8 @@ input_handle_character(u_char ch, struct input_ctx *ictx) log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch); if (s->cx == screen_size_x(s)) { - if (!screen_hidden(s)) { - input_store8(ictx->b, '\r'); - input_store8(ictx->b, '\n'); - } + input_write(ictx, TTY_CHARACTER, '\r'); + input_write(ictx, TTY_CHARACTER, '\n'); s->cx = 0; screen_display_cursor_down(s); @@ -384,8 +395,7 @@ input_handle_character(u_char ch, struct input_ctx *ictx) return; screen_display_cursor_set(s, ch); - if (!screen_hidden(s)) - input_store8(ictx->b, ch); + input_write(ictx, TTY_CHARACTER, ch); s->cx++; } @@ -399,7 +409,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) switch (ch) { case '\0': /* NUL */ - break; + return; case '\n': /* LF */ screen_display_cursor_down(s); break; @@ -419,28 +429,21 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) s->cx = 0; screen_display_cursor_down(s); } - if (screen_hidden(s)) - return; - input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); return; case '\016': /* SO */ s->attr |= ATTR_DRAWING; - if (screen_hidden(s)) - return; - input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); + input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); return; case '\017': /* SI */ s->attr &= ~ATTR_DRAWING; - if (screen_hidden(s)) - return; - input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); + input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); return; default: log_debug("unknown c0: %hhu", ch); return; } - if (!screen_hidden(s)) - input_store8(ictx->b, ch); + input_write(ictx, TTY_CHARACTER, ch); } void @@ -453,8 +456,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) switch (ch) { case 'M': /* RI */ screen_display_cursor_up(s); - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_REVERSEINDEX); + input_write(ictx, TTY_REVERSEINDEX); break; default: log_debug("unknown c1: %hhu", ch); @@ -471,12 +473,10 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx) switch (ch) { case '=': /* DECKPAM */ - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_KKEYPADON); + input_write(ictx, TTY_KKEYPADON); break; case '>': /* DECKPNM*/ - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_KKEYPADOFF); + input_write(ictx, TTY_KKEYPADOFF); break; case '7': /* DECSC */ s->saved_cx = s->cx; @@ -492,10 +492,8 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx) s->cy = s->saved_cy; s->attr = s->saved_attr; s->colr = s->saved_colr; - if (screen_hidden(s)) - break; - input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); - input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); break; default: log_debug("unknown p2: %hhu", ch); @@ -583,8 +581,7 @@ input_handle_sequence_cuu(struct input_ctx *ictx) } s->cy -= n; - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_CURSORUP, n); + input_write(ictx, TTY_CURSORUP, n); } void @@ -606,8 +603,7 @@ input_handle_sequence_cud(struct input_ctx *ictx) input_limit(n, 1, screen_last_y(s) - s->cy); s->cy += n; - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_CURSORDOWN, n); + input_write(ictx, TTY_CURSORDOWN, n); } void @@ -629,8 +625,7 @@ input_handle_sequence_cuf(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); s->cx += n; - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_CURSORRIGHT, n); + input_write(ictx, TTY_CURSORRIGHT, n); } void @@ -653,8 +648,7 @@ input_handle_sequence_cub(struct input_ctx *ictx) } s->cx -= n; - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_CURSORLEFT, n); + input_write(ictx, TTY_CURSORLEFT, n); } void @@ -676,8 +670,7 @@ input_handle_sequence_dch(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); screen_display_delete_characters(s, s->cx, s->cy, n); - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_DELETECHARACTER, n); + input_write(ictx, TTY_DELETECHARACTER, n); } void @@ -702,8 +695,7 @@ input_handle_sequence_dl(struct input_ctx *ictx) screen_display_delete_lines(s, s->cy, n); else screen_display_delete_lines_region(s, s->cy, n); - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_DELETELINE, n); + input_write(ictx, TTY_DELETELINE, n); } void @@ -725,8 +717,7 @@ input_handle_sequence_ich(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); screen_display_insert_characters(s, s->cx, s->cy, n); - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_INSERTCHARACTER, n); + input_write(ictx, TTY_INSERTCHARACTER, n); } void @@ -751,8 +742,7 @@ input_handle_sequence_il(struct input_ctx *ictx) screen_display_insert_lines(s, s->cy, n); else screen_display_insert_lines_region(s, s->cy, n); - if (!screen_hidden(s)) - input_store_one(ictx->b, CODE_INSERTLINE, n); + input_write(ictx, TTY_INSERTLINE, n); } void @@ -774,8 +764,7 @@ input_handle_sequence_vpa(struct input_ctx *ictx) input_limit(n, 1, screen_size_y(s)); s->cy = n - 1; - if (!screen_hidden(s)) - input_store_two(ictx->b, CODE_CURSORMOVE, n, s->cx + 1); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); } void @@ -797,8 +786,7 @@ input_handle_sequence_hpa(struct input_ctx *ictx) input_limit(n, 1, screen_size_x(s)); s->cx = n - 1; - if (!screen_hidden(s)) - input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, n); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); } void @@ -822,8 +810,7 @@ input_handle_sequence_cup(struct input_ctx *ictx) s->cx = m - 1; s->cy = n - 1; - if (!screen_hidden(s)) - input_store_two(ictx->b, CODE_CURSORMOVE, n, m); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); } void @@ -849,28 +836,21 @@ input_handle_sequence_ed(struct input_ctx *ictx) screen_display_fill_cursor_eos( s, SCREEN_DEFDATA, s->attr, s->colr); - if (screen_hidden(s)) - break; - input_store_zero(ictx->b, CODE_CLEARLINE); - for (i = s->cy + 1; i < screen_size_y(s); i++) { - input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); - input_store_zero(ictx->b, CODE_CLEARLINE); + for (i = s->cy; i < screen_size_y(s); i++) { + input_write(ictx, TTY_CURSORMOVE, i, 0); + input_write(ictx, TTY_CLEARENDOFLINE); } - input_store_two( - ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); break; case 2: screen_display_fill_lines( s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr); - if (screen_hidden(s)) - break; for (i = 0; i < screen_size_y(s); i++) { - input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); - input_store_zero(ictx->b, CODE_CLEARLINE); + input_write(ictx, TTY_CURSORMOVE, i, 0); + input_write(ictx, TTY_CLEARENDOFLINE); } - input_store_two( - ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); break; } } @@ -896,23 +876,17 @@ input_handle_sequence_el(struct input_ctx *ictx) case 0: screen_display_fill_cursor_eol( s, SCREEN_DEFDATA, s->attr, s->colr); - - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_CLEARENDOFLINE); + input_write(ictx, TTY_CLEARENDOFLINE); break; case 1: screen_display_fill_cursor_bol( s, SCREEN_DEFDATA, s->attr, s->colr); - - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE); + input_write(ictx, TTY_CLEARSTARTOFLINE); break; case 2: screen_display_fill_line( s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); - - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_CLEARLINE); + input_write(ictx, TTY_CLEARLINE); break; } } @@ -932,13 +906,11 @@ input_handle_sequence_sm(struct input_ctx *ictx) switch (n) { case 1: /* GATM */ s->mode |= MODE_KCURSOR; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_KCURSORON); + input_write(ictx, TTY_KCURSORON); break; case 25: /* TCEM */ s->mode |= MODE_CURSOR; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_CURSORON); + input_write(ictx, TTY_CURSORON); break; default: log_debug("unknown SM [%hhu]: %u", ictx->private, n); @@ -948,8 +920,7 @@ input_handle_sequence_sm(struct input_ctx *ictx) switch (n) { case 4: /* IRM */ s->mode |= MODE_INSERT; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_INSERTON); + input_write(ictx, TTY_INSERTON); break; case 34: /* Cursor high visibility not supported. */ @@ -976,13 +947,11 @@ input_handle_sequence_rm(struct input_ctx *ictx) switch (n) { case 1: /* GATM */ s->mode &= ~MODE_KCURSOR; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_KCURSOROFF); + input_write(ictx, TTY_KCURSOROFF); break; case 25: /* TCEM */ s->mode &= ~MODE_CURSOR; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_CURSOROFF); + input_write(ictx, TTY_CURSOROFF); break; default: log_debug("unknown RM [%hhu]: %u", ictx->private, n); @@ -992,8 +961,7 @@ input_handle_sequence_rm(struct input_ctx *ictx) switch (n) { case 4: /* IRM */ s->mode &= ~MODE_INSERT; - if (!screen_hidden(s)) - input_store_zero(ictx->b, CODE_INSERTOFF); + input_write(ictx, TTY_INSERTOFF); break; case 34: /* Cursor high visibility not supported. */ @@ -1067,8 +1035,7 @@ input_handle_sequence_decstbm(struct input_ctx *ictx) s->rupper = n - 1; s->rlower = m - 1; - if (!screen_hidden(s)) - input_store_two(ictx->b, CODE_SCROLLREGION, n, m); + input_write(ictx, TTY_SCROLLREGION, s->rupper, s->rlower); } void @@ -1152,67 +1119,5 @@ input_handle_sequence_sgr(struct input_ctx *ictx) } } } - if (!screen_hidden(s)) - input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); -} - -void -input_store_zero(struct buffer *b, u_char code) -{ - input_store8(b, '\e'); - input_store8(b, code); -} - -void -input_store_one(struct buffer *b, u_char code, uint16_t ua) -{ - input_store8(b, '\e'); - input_store8(b, code); - input_store16(b, ua); -} - -void -input_store_two(struct buffer *b, u_char code, uint16_t ua, uint16_t ub) -{ - input_store8(b, '\e'); - input_store8(b, code); - input_store16(b, ua); - input_store16(b, ub); -} - -void -input_store8(struct buffer *b, uint8_t n) -{ - buffer_ensure(b, 1); - BUFFER_IN(b)[0] = n; - buffer_add(b, 1); -} - -void -input_store16(struct buffer *b, uint16_t n) -{ - buffer_ensure(b, 2); - BUFFER_IN(b)[0] = n & 0xff; - BUFFER_IN(b)[1] = n >> 8; - buffer_add(b, 2); -} - -uint8_t -input_extract8(struct buffer *b) -{ - uint8_t n; - - n = BUFFER_OUT(b)[0]; - buffer_remove(b, 1); - return (n); -} - -uint16_t -input_extract16(struct buffer *b) -{ - uint16_t n; - - n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8); - buffer_remove(b, 2); - return (n); + input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); } diff --git a/key-bindings.c b/key-bindings.c index d6be315d..d2f51b25 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.21 2007-11-23 17:52:54 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.22 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -204,5 +204,5 @@ key_bindings_dispatch(int key, struct client *c) cmd_exec(bd->cmd, &ctx); if (c->session->curw->window->mode == &window_more_mode) - server_redraw_window_all(c->session->curw->window); + server_redraw_window(c->session->curw->window); } diff --git a/local.c b/local.c deleted file mode 100644 index 84a8c670..00000000 --- a/local.c +++ /dev/null @@ -1,793 +0,0 @@ -/* $Id: local.c,v 1.23 2007-11-26 20:36:30 nicm Exp $ */ - -/* - * Copyright (c) 2007 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include -#include -#include -#include -#define TTYDEFCHARS -/* glibc requires unistd.h before termios.h for TTYDEFCHARS. */ -#include -#include -#include - -#include "tmux.h" - -/* - * Functions to translate input and write output to the local client terminal. - * This file should probably be called tty or terminal.c. - */ - -int local_cmp(const void *, const void *); -int local_putc(int); -void local_putp(const char *); -void local_attributes(u_char, u_char); -u_char local_translate_acs(u_char); - -/* Local key types and key codes. */ -struct local_key { - const char *name; - char *string; - size_t size; - int code; -}; -struct local_key local_keys[] = { - { "ka1", NULL, 0, KEYC_A1 }, - { "ka3", NULL, 0, KEYC_A3 }, - { "kb2", NULL, 0, KEYC_B2 }, - { "kbeg", NULL, 0, KEYC_BEG }, - { "kcbt", NULL, 0, KEYC_BTAB }, - { "kc1", NULL, 0, KEYC_C1 }, - { "kc3", NULL, 0, KEYC_C3 }, - { "kcan", NULL, 0, KEYC_CANCEL }, - { "ktbc", NULL, 0, KEYC_CATAB }, - { "kclr", NULL, 0, KEYC_CLEAR }, - { "kclo", NULL, 0, KEYC_CLOSE }, - { "kcmd", NULL, 0, KEYC_COMMAND }, - { "kcpy", NULL, 0, KEYC_COPY }, - { "kcrt", NULL, 0, KEYC_CREATE }, - { "kctab", NULL, 0, KEYC_CTAB }, - { "kdch1", NULL, 0, KEYC_DC }, - { "kdl1", NULL, 0, KEYC_DL }, - { "kcud1", NULL, 0, KEYC_DOWN }, - { "krmir", NULL, 0, KEYC_EIC }, - { "kend", NULL, 0, KEYC_END }, - { "kent", NULL, 0, KEYC_ENTER }, - { "kel", NULL, 0, KEYC_EOL }, - { "ked", NULL, 0, KEYC_EOS }, - { "kext", NULL, 0, KEYC_EXIT }, - { "kf0", NULL, 0, KEYC_F0 }, - { "kf1", NULL, 0, KEYC_F1 }, - { "kf10", NULL, 0, KEYC_F10 }, - { "kf11", NULL, 0, KEYC_F11 }, - { "kf12", NULL, 0, KEYC_F12 }, - { "kf13", NULL, 0, KEYC_F13 }, - { "kf14", NULL, 0, KEYC_F14 }, - { "kf15", NULL, 0, KEYC_F15 }, - { "kf16", NULL, 0, KEYC_F16 }, - { "kf17", NULL, 0, KEYC_F17 }, - { "kf18", NULL, 0, KEYC_F18 }, - { "kf19", NULL, 0, KEYC_F19 }, - { "kf2", NULL, 0, KEYC_F2 }, - { "kf20", NULL, 0, KEYC_F20 }, - { "kf21", NULL, 0, KEYC_F21 }, - { "kf22", NULL, 0, KEYC_F22 }, - { "kf23", NULL, 0, KEYC_F23 }, - { "kf24", NULL, 0, KEYC_F24 }, - { "kf25", NULL, 0, KEYC_F25 }, - { "kf26", NULL, 0, KEYC_F26 }, - { "kf27", NULL, 0, KEYC_F27 }, - { "kf28", NULL, 0, KEYC_F28 }, - { "kf29", NULL, 0, KEYC_F29 }, - { "kf3", NULL, 0, KEYC_F3 }, - { "kf30", NULL, 0, KEYC_F30 }, - { "kf31", NULL, 0, KEYC_F31 }, - { "kf32", NULL, 0, KEYC_F32 }, - { "kf33", NULL, 0, KEYC_F33 }, - { "kf34", NULL, 0, KEYC_F34 }, - { "kf35", NULL, 0, KEYC_F35 }, - { "kf36", NULL, 0, KEYC_F36 }, - { "kf37", NULL, 0, KEYC_F37 }, - { "kf38", NULL, 0, KEYC_F38 }, - { "kf39", NULL, 0, KEYC_F39 }, - { "kf4", NULL, 0, KEYC_F4 }, - { "kf40", NULL, 0, KEYC_F40 }, - { "kf41", NULL, 0, KEYC_F41 }, - { "kf42", NULL, 0, KEYC_F42 }, - { "kf43", NULL, 0, KEYC_F43 }, - { "kf44", NULL, 0, KEYC_F44 }, - { "kf45", NULL, 0, KEYC_F45 }, - { "kf46", NULL, 0, KEYC_F46 }, - { "kf47", NULL, 0, KEYC_F47 }, - { "kf48", NULL, 0, KEYC_F48 }, - { "kf49", NULL, 0, KEYC_F49 }, - { "kf5", NULL, 0, KEYC_F5 }, - { "kf50", NULL, 0, KEYC_F50 }, - { "kf51", NULL, 0, KEYC_F51 }, - { "kf52", NULL, 0, KEYC_F52 }, - { "kf53", NULL, 0, KEYC_F53 }, - { "kf54", NULL, 0, KEYC_F54 }, - { "kf55", NULL, 0, KEYC_F55 }, - { "kf56", NULL, 0, KEYC_F56 }, - { "kf57", NULL, 0, KEYC_F57 }, - { "kf58", NULL, 0, KEYC_F58 }, - { "kf59", NULL, 0, KEYC_F59 }, - { "kf6", NULL, 0, KEYC_F6 }, - { "kf60", NULL, 0, KEYC_F60 }, - { "kf61", NULL, 0, KEYC_F61 }, - { "kf62", NULL, 0, KEYC_F62 }, - { "kf63", NULL, 0, KEYC_F63 }, - { "kf7", NULL, 0, KEYC_F7 }, - { "kf8", NULL, 0, KEYC_F8 }, - { "kf9", NULL, 0, KEYC_F9 }, - { "kfnd", NULL, 0, KEYC_FIND }, - { "khlp", NULL, 0, KEYC_HELP }, - { "khome", NULL, 0, KEYC_HOME }, - { "kich1", NULL, 0, KEYC_IC }, - { "kil1", NULL, 0, KEYC_IL }, - { "kcub1", NULL, 0, KEYC_LEFT }, - { "kll", NULL, 0, KEYC_LL }, - { "kmrk", NULL, 0, KEYC_MARK }, - { "kmsg", NULL, 0, KEYC_MESSAGE }, - { "kmov", NULL, 0, KEYC_MOVE }, - { "knxt", NULL, 0, KEYC_NEXT }, - { "knp", NULL, 0, KEYC_NPAGE }, - { "kopn", NULL, 0, KEYC_OPEN }, - { "kopt", NULL, 0, KEYC_OPTIONS }, - { "kpp", NULL, 0, KEYC_PPAGE }, - { "kprv", NULL, 0, KEYC_PREVIOUS }, - { "kprt", NULL, 0, KEYC_PRINT }, - { "krdo", NULL, 0, KEYC_REDO }, - { "kref", NULL, 0, KEYC_REFERENCE }, - { "krfr", NULL, 0, KEYC_REFRESH }, - { "krpl", NULL, 0, KEYC_REPLACE }, - { "krst", NULL, 0, KEYC_RESTART }, - { "kres", NULL, 0, KEYC_RESUME }, - { "kcuf1", NULL, 0, KEYC_RIGHT }, - { "ksav", NULL, 0, KEYC_SAVE }, - { "kBEG", NULL, 0, KEYC_SBEG }, - { "kCAN", NULL, 0, KEYC_SCANCEL }, - { "kCMD", NULL, 0, KEYC_SCOMMAND }, - { "kCPY", NULL, 0, KEYC_SCOPY }, - { "kCRT", NULL, 0, KEYC_SCREATE }, - { "kDC", NULL, 0, KEYC_SDC }, - { "kDL", NULL, 0, KEYC_SDL }, - { "kslt", NULL, 0, KEYC_SELECT }, - { "kEND", NULL, 0, KEYC_SEND }, - { "kEOL", NULL, 0, KEYC_SEOL }, - { "kEXT", NULL, 0, KEYC_SEXIT }, - { "kind", NULL, 0, KEYC_SF }, - { "kFND", NULL, 0, KEYC_SFIND }, - { "kHLP", NULL, 0, KEYC_SHELP }, - { "kHOM", NULL, 0, KEYC_SHOME }, - { "kIC", NULL, 0, KEYC_SIC }, - { "kLFT", NULL, 0, KEYC_SLEFT }, - { "kMSG", NULL, 0, KEYC_SMESSAGE }, - { "kMOV", NULL, 0, KEYC_SMOVE }, - { "kNXT", NULL, 0, KEYC_SNEXT }, - { "kOPT", NULL, 0, KEYC_SOPTIONS }, - { "kPRV", NULL, 0, KEYC_SPREVIOUS }, - { "kPRT", NULL, 0, KEYC_SPRINT }, - { "kri", NULL, 0, KEYC_SR }, - { "kRDO", NULL, 0, KEYC_SREDO }, - { "kRPL", NULL, 0, KEYC_SREPLACE }, - { "kRIT", NULL, 0, KEYC_SRIGHT }, - { "kRES", NULL, 0, KEYC_SRSUME }, - { "kSAV", NULL, 0, KEYC_SSAVE }, - { "kSPD", NULL, 0, KEYC_SSUSPEND }, - { "khts", NULL, 0, KEYC_STAB }, - { "kUND", NULL, 0, KEYC_SUNDO }, - { "kspd", NULL, 0, KEYC_SUSPEND }, - { "kund", NULL, 0, KEYC_UNDO }, - { "kcuu1", NULL, 0, KEYC_UP }, - { "pmous", NULL, 0, KEYC_MOUSE }, - { NULL, NULL, 0, KEYC_NONE } -}; - -/* tty file descriptor and local terminal buffers. */ -int local_fd = -1; -int local_log = -1; -struct buffer *local_in; -struct buffer *local_out; -struct termios local_tio; -u_char local_attr; -u_char local_colr; - -/* Initialise local terminal. */ -int -local_init(struct buffer **in, struct buffer **out) -{ - char *tty, *path; - const char *name; - int mode, error; - struct termios tio; - struct local_key *lk; - u_int i, j; - static const char *const reqd[] = { - "carriage_return", - "change_scroll_region", - "clear_screen", - "clr_bol", - "clr_eol", - "cursor_address", - "cursor_left", - "cursor_down", - "parm_dch", - "parm_delete_line", - "parm_down_cursor", - "parm_ich", - "parm_insert_line", - "parm_left_cursor", - "parm_right_cursor", - "parm_up_cursor", - "scroll_reverse", - NULL - }; - - if ((tty = ttyname(STDIN_FILENO)) == NULL) - fatal("ttyname failed"); - if ((local_fd = open(tty, O_RDWR)) == -1) - fatal("open failed"); - if ((mode = fcntl(local_fd, F_GETFL)) == -1) - fatal("fcntl failed"); - if (fcntl(local_fd, F_SETFL, mode|O_NONBLOCK) == -1) - fatal("fcntl failed"); - - if ((name = getenv("TERM")) == NULL || *name == '\0') - name = "unknown"; - if (newterm(name, stdout, stdin) == NULL) { - log_warnx("error opening terminal: %s", name); - return (-1); - } - for (i = 0; reqd[i] != NULL; i++) { - error = 0; - - for (j = 0; strfnames[j] != NULL; j++) { - if (strcmp(strfnames[j], reqd[i]) == 0) { - if (strcodes[j] == NULL) - error = -1; - break; - } - } - if (error != -1) { - for (j = 0; numfnames[j] != NULL; j++) { - if (strcmp(numfnames[j], reqd[i]) == 0) { - if (numcodes[j] == NULL) - error = -1; - break; - } - } - } - if (error != -1) { - for (j = 0; boolfnames[j] != NULL; j++) { - if (strcmp(boolfnames[j], reqd[i]) == 0) { - if (boolcodes[j] == NULL) - error = -1; - break; - } - } - } - - if (error == -1) { - log_warnx("required capability missing: %s", reqd[i]); - return (-1); - } - } - - *in = local_in = buffer_create(BUFSIZ); - *out = local_out = buffer_create(BUFSIZ); - - if (tcgetattr(local_fd, &local_tio) != 0) - fatal("tcgetattr failed"); - memset(&tio, 0, sizeof tio); - tio.c_iflag = TTYDEF_IFLAG & ~(IXON|IXOFF|ICRNL|INLCR); - tio.c_oflag = TTYDEF_OFLAG & ~(OPOST|ONLCR|OCRNL|ONLRET); - tio.c_lflag = - TTYDEF_LFLAG & ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG); - tio.c_cflag = TTYDEF_CFLAG; - memcpy(&tio.c_cc, ttydefchars, sizeof tio.c_cc); - cfsetspeed(&tio, TTYDEF_SPEED); - if (tcsetattr(local_fd, TCSANOW, &tio) != 0) - fatal("tcsetattr failed"); - - if (enter_ca_mode != NULL) - local_putp(enter_ca_mode); - if (keypad_xmit != NULL) - local_putp(keypad_xmit); - if (ena_acs != NULL) - local_putp(ena_acs); - local_putp(clear_screen); - - for (lk = local_keys; lk->name != NULL; lk++) { - lk->string = tigetstr(lk->name); - if (lk->string == (char *) -1 || lk->string == (char *) 0) - lk->string = NULL; - else { - lk->size = strlen(lk->string); - log_debug("string for %s (%d): \"%s\", length %zu", - lk->name, lk->code, lk->string, lk->size); - } - } - qsort(local_keys, sizeof local_keys / - sizeof local_keys[0], sizeof local_keys[0], local_cmp); - - local_attr = 0; - local_colr = 0x88; - - if (debug_level > 2) { - xasprintf( - &path, "%s-output-%ld.log", __progname,(long) getpid()); - local_log = open( - path, O_RDWR|O_APPEND|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - xfree(path); - } - - return (local_fd); -} - -/* Compare keys. */ -int -local_cmp(const void *ptr1, const void *ptr2) -{ - const struct local_key *lk1 = ptr1, *lk2 = ptr2; - - if (lk1->string == NULL && lk2->string == NULL) - return (0); - if (lk1->string == NULL) - return (1); - if (lk2->string == NULL) - return (-1); - return (lk2->size - lk1->size); -} - -/* Tidy up and reset local terminal. */ -void -local_done(void) -{ - struct winsize ws; - - buffer_destroy(local_in); - buffer_destroy(local_out); - - if (tcsetattr(local_fd, TCSANOW, &local_tio) != 0) - fatal("tcsetattr failed"); - close(local_fd); - - if (local_log != -1) - close(local_log); - - if (change_scroll_region != NULL) { - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) - fatal("ioctl(TIOCGWINSZ)"); - putp(tparm(change_scroll_region, 0, ws.ws_row - 1)); - } - - endwin(); - if (keypad_local != NULL) - putp(keypad_local); /* not local_putp */ - if (exit_ca_mode != NULL) - putp(exit_ca_mode); - putp(clear_screen); - if (cursor_normal != NULL) - putp(cursor_normal); - if (exit_attribute_mode != NULL) - putp(exit_attribute_mode); -} - -/* Put a character. Used as parameter to tputs. */ -int -local_putc(int c) -{ - u_char ch = c; - - if (c < 0 || c > (int) UCHAR_MAX) - fatalx("invalid character"); - - if (local_log != -1) - write(local_log, &ch, 1); - if (acs_chars != NULL && local_attr & ATTR_DRAWING) { - ch = local_translate_acs(ch); - if (ch == '\0') - ch = '?'; - } - - buffer_write(local_out, &ch, 1); - return (c); -} - -/* Put terminfo string. */ -void -local_putp(const char *s) -{ - if (s == NULL) - fatalx("null pointer"); - - tputs(s, 1, local_putc); -} - -/* Return waiting keys if any. */ -int -local_key(void) -{ - struct local_key *lk; - u_int i; - size_t size; - - size = BUFFER_USED(local_in); - if (size == 0) - return (KEYC_NONE); - - i = 0; - lk = local_keys; - while (lk->string != NULL) { - if (strncmp(BUFFER_OUT(local_in), lk->string, size) == 0) { - if (size < lk->size) - return (KEYC_NONE); - log_debug("got key: " - "%s %d \"%s\"", lk->name, lk->code, lk->string); - buffer_remove(local_in, lk->size); - return (lk->code); - } - - i++; - lk = local_keys + i; - } - - return (input_extract8(local_in)); -} - -/* Display output data. */ -void -local_output(struct buffer *b, size_t size) -{ - u_char ch; - uint16_t ua, ub; - - while (size != 0) { - if (size < 1) - break; - size--; - ch = input_extract8(b); - if (ch != '\e') { - switch (ch) { - case '\n': /* LF */ - local_putp(cursor_down); - break; - case '\r': /* CR */ - local_putp(carriage_return); - break; - case '\007': /* BEL */ - if (bell != NULL) - local_putp(bell); - break; - case '\010': /* BS */ - local_putp(cursor_left); - break; - default: - local_putc(ch); - break; - } - continue; - } - - if (size < 1) - fatalx("underflow"); - size--; - ch = input_extract8(b); - - log_debug("received code %hhu", ch); - switch (ch) { - case CODE_CURSORUP: - if (size < 2) - fatalx("CODE_CURSORUP underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_up_cursor, ua)); - break; - case CODE_CURSORDOWN: - if (size < 2) - fatalx("CODE_CURSORDOWN underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_down_cursor, ua)); - break; - case CODE_CURSORRIGHT: - if (size < 2) - fatalx("CODE_CURSORRIGHT underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_right_cursor, ua)); - break; - case CODE_CURSORLEFT: - if (size < 2) - fatalx("CODE_CURSORLEFT underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_left_cursor, ua)); - break; - case CODE_CURSORMOVE: - if (size < 4) - fatalx("CODE_CURSORMOVE underflow"); - size -= 4; - ua = input_extract16(b); - ub = input_extract16(b); - local_putp(tparm(cursor_address, ua - 1, ub - 1)); - break; - case CODE_CLEARENDOFLINE: - local_putp(clr_eol); - break; - case CODE_CLEARSTARTOFLINE: - local_putp(clr_bol); - break; - case CODE_CLEARLINE: - local_putp(clr_eol); /* XXX */ - break; - case CODE_INSERTLINE: - if (size < 2) - fatalx("CODE_INSERTLINE underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_insert_line, ua)); - break; - case CODE_DELETELINE: - if (size < 2) - fatalx("CODE_DELETELINE underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_delete_line, ua)); - break; - case CODE_INSERTCHARACTER: - if (size < 2) - fatalx("CODE_INSERTCHARACTER underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_ich, ua)); - break; - case CODE_DELETECHARACTER: - if (size < 2) - fatalx("CODE_DELETECHARACTER underflow"); - size -= 2; - ua = input_extract16(b); - local_putp(tparm(parm_dch, ua)); - break; - case CODE_CURSORON: - if (cursor_normal != NULL) - local_putp(cursor_normal); - break; - case CODE_CURSOROFF: - if (cursor_invisible != NULL) - local_putp(cursor_invisible); - break; - case CODE_REVERSEINDEX: - local_putp(scroll_reverse); - break; - case CODE_SCROLLREGION: - if (size < 4) - fatalx("CODE_SCROLLREGION underflow"); - size -= 4; - ua = input_extract16(b); - ub = input_extract16(b); - local_putp(tparm(change_scroll_region, ua - 1, ub - 1)); - break; - case CODE_INSERTON: - if (enter_insert_mode != NULL) - local_putp(enter_insert_mode); - break; - case CODE_INSERTOFF: - if (exit_insert_mode != NULL) - local_putp(exit_insert_mode); - break; - case CODE_KCURSOROFF: - /* - t = tigetstr("CE"); - if (t != (char *) 0 && t != (char *) -1) - local_putp(t); - */ - break; - case CODE_KCURSORON: - /* - t = tigetstr("CS"); - if (t != (char *) 0 && t != (char *) -1) - local_putp(t); - */ - break; - case CODE_KKEYPADOFF: - /* - if (keypad_local != NULL) - local_putp(keypad_local); - */ - break; - case CODE_KKEYPADON: - /* - if (keypad_xmit != NULL) - local_putp(keypad_xmit); - */ - break; - case CODE_TITLE: - if (size < 2) - fatalx("CODE_TITLE underflow"); - size -= 2; - ua = input_extract16(b); - - if (size < ua) - fatalx("CODE_TITLE underflow"); - size -= ua; - buffer_remove(b, ua); - break; - case CODE_ATTRIBUTES: - if (size < 4) - fatalx("CODE_ATTRIBUTES underflow"); - size -= 4; - ua = input_extract16(b); - ub = input_extract16(b); - - local_attributes(ua, ub); - break; - } - } -} - -void -local_attributes(u_char attr, u_char colr) -{ - u_char fg, bg; - - if (attr == local_attr && colr == local_colr) - return; - - /* If any bits are being cleared, reset everything. */ - if (local_attr & ~attr) { - if ((local_attr & ATTR_DRAWING) && - exit_alt_charset_mode != NULL) - local_putp(exit_alt_charset_mode); - local_putp(exit_attribute_mode); - local_colr = 0x88; - local_attr = 0; - } - - /* Filter out bits already set. */ - attr &= ~local_attr; - local_attr |= attr; - - if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL) - local_putp(enter_bold_mode); - if ((attr & ATTR_DIM) && enter_dim_mode != NULL) - local_putp(enter_dim_mode); - if ((attr & ATTR_ITALICS) && enter_standout_mode != NULL) - local_putp(enter_standout_mode); - if ((attr & ATTR_UNDERSCORE) && enter_underline_mode != NULL) - local_putp(enter_underline_mode); - if ((attr & ATTR_BLINK) && enter_blink_mode != NULL) - local_putp(enter_blink_mode); - if ((attr & ATTR_REVERSE) && enter_reverse_mode != NULL) - local_putp(enter_reverse_mode); - if ((attr & ATTR_HIDDEN) && enter_secure_mode != NULL) - local_putp(enter_secure_mode); - if ((attr & ATTR_DRAWING) && enter_alt_charset_mode != NULL) - local_putp(enter_alt_charset_mode); - - fg = (colr >> 4) & 0xf; - if (fg != ((local_colr >> 4) & 0xf)) { - if (tigetflag("AX") == TRUE) { - if (fg == 7) - fg = 8; - } else { - if (fg == 8) - fg = 7; - } - - if (fg == 8) - local_putp("\e[39m"); - else if (set_a_foreground != NULL) - local_putp(tparm(set_a_foreground, fg)); - } - - bg = colr & 0xf; - if (bg != (local_colr & 0xf)) { - if (tigetflag("AX") == TRUE) { - if (bg == 0) - bg = 8; - } else { - if (bg == 8) - bg = 0; - } - - if (bg == 8) - local_putp("\e[49m"); - else if (set_a_background != NULL) - local_putp(tparm(set_a_background, bg)); - } - - local_colr = colr; -} - -u_char -local_translate_acs(u_char ch) -{ - switch (ch) { - case '~': - return (ACS_BULLET); - case '}': - return (ACS_STERLING); - case '|': - return (ACS_NEQUAL); - case '{': - return (ACS_PI); - case 'z': - return (ACS_GEQUAL); - case 'y': - return (ACS_LEQUAL); - case 'x': - return (ACS_VLINE); - case 'w': - return (ACS_TTEE); - case 'v': - return (ACS_BTEE); - case 'u': - return (ACS_RTEE); - case 't': - return (ACS_LTEE); - case 's': - return (ACS_S9); - case 'r': - return (ACS_S7); - case 'q': - return (ACS_HLINE); - case 'p': - return (ACS_S3); - case 'o': - return (ACS_S1); - case 'n': - return (ACS_PLUS); - case 'm': - return (ACS_LLCORNER); - case 'l': - return (ACS_ULCORNER); - case 'k': - return (ACS_URCORNER); - case 'j': - return (ACS_LRCORNER); - case 'i': - return (ACS_LANTERN); - case 'h': - return (ACS_BOARD); - case 'g': - return (ACS_PLMINUS); - case 'f': - return (ACS_DEGREE); - case 'a': - return (ACS_CKBOARD); - case '`': - return (ACS_DIAMOND); - case '0': - return (ACS_BLOCK); - case '.': - return (ACS_DARROW); - case '-': - return (ACS_UARROW); - case ',': - return (ACS_LARROW); - case '+': - return (ACS_RARROW); - } - return (ch); -} diff --git a/resize.c b/resize.c index a48f5c0a..8fed0eef 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.6 2007-11-21 13:11:41 nicm Exp $ */ +/* $Id: resize.c,v 1.7 2007-11-27 19:23:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -117,8 +117,8 @@ recalculate_sizes(void) log_debug("window size %u,%u (was %u,%u)", ssx, ssy, screen_size_x(&w->screen), screen_size_y(&w->screen)); - server_clear_window_cur(w); window_resize(w, ssx, ssy); - server_redraw_window_cur(w); + server_clear_window(w); + server_redraw_window(w); } } diff --git a/screen.c b/screen.c index dc2c5065..4f6824e8 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.49 2007-11-26 22:06:11 nicm Exp $ */ +/* $Id: screen.c,v 1.50 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -267,13 +267,45 @@ screen_destroy(struct screen *s) xfree(s->grid_size); } +/* Initialise redrawing a window. */ +void +screen_draw_start_window( + struct screen_draw_ctx *ctx, struct window *w, u_int ox, u_int oy) +{ + struct screen *t = &w->screen; + + screen_draw_start(ctx, t, tty_write_window, w, ox, oy); +} + +/* Initialise redrawing a client. */ +void +screen_draw_start_client( + struct screen_draw_ctx *ctx, struct client *c, u_int ox, u_int oy) +{ + struct screen *t = &c->session->curw->window->screen; + + screen_draw_start(ctx, t, tty_write_client, c, ox, oy); +} + +/* Initialise redrawing a session. */ +void +screen_draw_start_session( + struct screen_draw_ctx *ctx, struct session *s, u_int ox, u_int oy) +{ + struct screen *t = &s->curw->window->screen; + + screen_draw_start(ctx, t, tty_write_session, s, ox, oy); +} + /* Initialise drawing. */ void -screen_draw_start(struct screen_draw_ctx *ctx, - struct screen *s, struct buffer *b, u_int ox, u_int oy) +screen_draw_start(struct screen_draw_ctx *ctx, struct screen *s, + void (*write)(void *, int, ...), void *data, u_int ox, u_int oy) { + ctx->write = write; + ctx->data = data; + ctx->s = s; - ctx->b = b; ctx->ox = ox; ctx->oy = oy; @@ -287,8 +319,8 @@ screen_draw_start(struct screen_draw_ctx *ctx, ctx->attr = s->attr; ctx->colr = s->colr; - input_store_two(b, CODE_SCROLLREGION, 1, screen_size_y(s)); - input_store_zero(b, CODE_CURSOROFF); + ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s)); + ctx->write(ctx->data, TTY_CURSOROFF); } /* Set selection. */ @@ -356,44 +388,112 @@ void screen_draw_stop(struct screen_draw_ctx *ctx) { struct screen *s = ctx->s; - struct buffer *b = ctx->b; - input_store_two(b, CODE_SCROLLREGION, s->rupper + 1, s->rlower + 1); + ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); if (ctx->cx != s->cx || ctx->cy != s->cy) - input_store_two(b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); if (ctx->attr != s->attr || ctx->colr != s->colr) - input_store_two(b, CODE_ATTRIBUTES, s->attr, s->colr); + ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr); if (s->mode & MODE_BACKGROUND) { if (s->mode & MODE_BGCURSOR) - input_store_zero(b, CODE_CURSORON); + ctx->write(ctx->data, TTY_CURSORON); } else { if (s->mode & MODE_CURSOR) - input_store_zero(b, CODE_CURSORON); + ctx->write(ctx->data, TTY_CURSORON); } } +/* Insert lines. */ +void +screen_draw_insert_lines(struct screen_draw_ctx *ctx, u_int ny) +{ + ctx->write(ctx->data, TTY_INSERTLINE, ny); +} + +/* Delete lines. */ +void +screen_draw_delete_lines(struct screen_draw_ctx *ctx, u_int ny) +{ + ctx->write(ctx->data, TTY_DELETELINE, ny); +} + +/* Insert characters. */ +void +screen_draw_insert_characters(struct screen_draw_ctx *ctx, u_int nx) +{ + ctx->write(ctx->data, TTY_INSERTCHARACTER, nx); +} + +/* Delete characters. */ +void +screen_draw_delete_characters(struct screen_draw_ctx *ctx, u_int nx) +{ + ctx->write(ctx->data, TTY_DELETECHARACTER, nx); +} + +/* Clear end of line. */ +void +screen_draw_clear_line_to(struct screen_draw_ctx *ctx, u_int px) +{ + while (ctx->cx <= px) { + ctx->write(ctx->data, TTY_CHARACTER, SCREEN_DEFDATA); + ctx->cx++; + } +} + +/* Clear screen. */ +void +screen_draw_clear_screen(struct screen_draw_ctx *ctx) +{ + u_int i; + + for (i = 0; i < screen_size_y(ctx->s); i++) { + screen_draw_move_cursor(ctx, 0, i); + screen_draw_clear_line_to(ctx, screen_size_x(ctx->s)); + } +} + +/* Write string. */ +void printflike2 +screen_draw_write_string(struct screen_draw_ctx *ctx, const char *fmt, ...) +{ + struct screen *s = ctx->s; + va_list ap; + char *msg, *ptr; + + va_start(ap, fmt); + xvasprintf(&msg, fmt, ap); + va_end(ap); + + for (ptr = msg; *ptr != '\0'; ptr++) { + if (ctx->cx > screen_last_x(s)) + break; + ctx->write(ctx->data, TTY_CHARACTER, *ptr); + ctx->cx++; + } + + xfree(msg); +} + /* Move cursor. */ void -screen_draw_move(struct screen_draw_ctx *ctx, u_int px, u_int py) +screen_draw_move_cursor(struct screen_draw_ctx *ctx, u_int px, u_int py) { if (px == ctx->cx && py == ctx->cy) return; - /* XXX disabled while things outside can move the cursor (eg - window-more.c writes characters) if (px == 0 && py == ctx->cy) - input_store8(ctx->b, '\r'); + ctx->write(ctx->data, TTY_CHARACTER, '\r'); else if (px == ctx->cx && py == ctx->cy + 1) - input_store8(ctx->b, '\n'); + ctx->write(ctx->data, TTY_CHARACTER, '\n'); else if (px == 0 && py == ctx->cy + 1) { - input_store8(ctx->b, '\r'); - input_store8(ctx->b, '\n'); + ctx->write(ctx->data, TTY_CHARACTER, '\r'); + ctx->write(ctx->data, TTY_CHARACTER, '\n'); } else - */ - input_store_two(ctx->b, CODE_CURSORMOVE, py + 1, px + 1); + ctx->write(ctx->data, TTY_CURSORMOVE, py, px); ctx->cx = px; ctx->cy = py; @@ -405,7 +505,7 @@ screen_draw_set_attributes( struct screen_draw_ctx *ctx, u_char attr, u_char colr) { if (attr != ctx->attr || colr != ctx->colr) { - input_store_two(ctx->b, CODE_ATTRIBUTES, attr, colr); + ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); ctx->attr = attr; ctx->colr = colr; } @@ -415,14 +515,13 @@ screen_draw_set_attributes( void screen_draw_cell(struct screen_draw_ctx *ctx, u_int px, u_int py) { - struct buffer *b = ctx->b; - u_char data, attr, colr; + u_char data, attr, colr; - screen_draw_move(ctx, px, py); + screen_draw_move_cursor(ctx, px, py); screen_draw_get_cell(ctx, px, py, &data, &attr, &colr); screen_draw_set_attributes(ctx, attr, colr); - input_store8(b, data); + ctx->write(ctx->data, TTY_CHARACTER, data); /* * Don't try to wrap as it will cause problems when screen is smaller @@ -465,8 +564,8 @@ screen_draw_line(struct screen_draw_ctx *ctx, u_int py) screen_draw_cells(ctx, 0, py, screen_size_x(ctx->s)); else { screen_draw_cells(ctx, 0, py, cx); - screen_draw_move(ctx, cx, py); - input_store_zero(ctx->b, CODE_CLEARENDOFLINE); + screen_draw_move_cursor(ctx, cx, py); + ctx->write(ctx->data, TTY_CLEARENDOFLINE); } } diff --git a/server-fn.c b/server-fn.c index 0e4a0f37..8caea797 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.34 2007-11-24 18:32:52 nicm Exp $ */ +/* $Id: server-fn.c,v 1.35 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -105,7 +105,7 @@ server_write_session( } void -server_write_window_cur( +server_write_window( struct window *w, enum hdrtype type, const void *buf, size_t len) { struct client *c; @@ -120,262 +120,144 @@ server_write_window_cur( } } -void -server_write_window_all( - struct window *w, enum hdrtype type, const void *buf, size_t len) -{ - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (session_has(c->session, w)) - server_write_client(c, type, buf, len); - } -} - -void -server_status_client(struct client *c) -{ - struct hdr hdr; - size_t size; - - if (status_lines == 0 || c->sy <= status_lines) - return; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - status_write(c); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); -} - void server_clear_client(struct client *c) { - struct screen *s = &c->session->curw->window->screen; - struct hdr hdr; - size_t size; - u_int i; + struct screen_draw_ctx ctx; - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - input_store_zero(c->out, CODE_CURSOROFF); - for (i = 0; i < screen_size_y(s); i++) { - input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1); - input_store_zero(c->out, CODE_CLEARLINE); - } - input_store_two(c->out, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); - if (s->mode & MODE_BACKGROUND) { - if (s->mode & MODE_BGCURSOR) - input_store_zero(c->out, CODE_CURSORON); - } else { - if (s->mode & MODE_CURSOR) - input_store_zero(c->out, CODE_CURSORON); - } - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); + screen_draw_start_client(&ctx, c, 0, 0); + screen_draw_clear_screen(&ctx); + screen_draw_stop(&ctx); + + status_write_client(c); } void server_redraw_client(struct client *c) { - struct window *w = c->session->curw->window; - struct hdr hdr; - size_t size; + struct screen_draw_ctx ctx; + struct window *w = c->session->curw->window; - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); + screen_draw_start_client(&ctx, c, 0, 0); + window_draw(w, &ctx, 0, screen_size_y(&w->screen)); + screen_draw_stop(&ctx); - window_draw(w, c->out, 0, screen_size_y(&w->screen)); + status_write_client(c); +} - size = BUFFER_USED(c->out) - size; - log_debug("redrawing window, %zu bytes", size); - if (size != 0) { - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } else - buffer_reverse_add(c->out, sizeof hdr); +void +server_status_client(struct client *c) +{ + status_write_client(c); +} - server_status_client(c); +void +server_clear_session(struct session *s) +{ + struct screen_draw_ctx ctx; + + screen_draw_start_session(&ctx, s, 0, 0); + screen_draw_clear_screen(&ctx); + screen_draw_stop(&ctx); + + status_write_session(s); } void server_redraw_session(struct session *s) { - struct client *c; - u_int i; + struct screen_draw_ctx ctx; + struct window *w = s->curw->window; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session == s) - server_redraw_client(c); - } + screen_draw_start_session(&ctx, s, 0, 0); + window_draw(w, &ctx, 0, screen_size_y(&w->screen)); + screen_draw_stop(&ctx); + + status_write_session(s); } void server_status_session(struct session *s) { - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session == s) - server_status_client(c); - } + status_write_session(s); } void -server_clear_window_cur(struct window *w) +server_clear_window(struct window *w) { - struct client *c; - u_int i; + struct screen_draw_ctx ctx; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && - c->session != NULL && c->session->curw->window == w) - server_clear_client(c); - } + screen_draw_start_window(&ctx, w, 0, 0); + screen_draw_clear_screen(&ctx); + screen_draw_stop(&ctx); + + status_write_window(w); } void -server_clear_window_all(struct window *w) +server_redraw_window(struct window *w) { - struct client *c; - u_int i; + struct screen_draw_ctx ctx; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (session_has(c->session, w)) - server_redraw_client(c); - } + screen_draw_start_window(&ctx, w, 0, 0); + window_draw(w, &ctx, 0, screen_size_y(&w->screen)); + screen_draw_stop(&ctx); + + status_write_window(w); } void -server_redraw_window_cur(struct window *w) +server_status_window(struct window *w) { - struct client *c; + struct session *s; u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && - c->session != NULL && c->session->curw->window == w) - server_redraw_client(c); - } -} + /* + * This is slightly different. We want to redraw the status line of any + * clients containing this window rather than any where it is the + * current window. + */ -void -server_redraw_window_all(struct window *w) -{ - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (session_has(c->session, w)) - server_redraw_client(c); - } -} - -void -server_status_window_cur(struct window *w) -{ - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && - c->session != NULL && c->session->curw->window == w) - server_status_client(c); - } -} - -void -server_status_window_all(struct window *w) -{ - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (session_has(c->session, w)) - server_status_client(c); + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + s = ARRAY_ITEM(&sessions, i); + if (s != NULL && session_has(s, w)) + server_status_session(s); } } void printflike2 server_write_message(struct client *c, const char *fmt, ...) { - struct window *w = c->session->curw->window; struct screen_draw_ctx ctx; - struct hdr hdr; va_list ap; char *msg; size_t size; - u_int i; - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, &w->screen, c->out, 0, 0); - screen_draw_move(&ctx, 0, c->sy - 1); + screen_draw_start_client(&ctx, c, 0, 0); + screen_draw_move_cursor(&ctx, 0, c->sy - 1); screen_draw_set_attributes(&ctx, ATTR_REVERSE, 0x88); + va_start(ap, fmt); xvasprintf(&msg, fmt, ap); va_end(ap); - if (strlen(msg) > c->sx - 1) + + size = strlen(msg); + if (size < c->sx - 1) { + msg = xrealloc(msg, 1, c->sx); msg[c->sx - 1] = '\0'; - buffer_write(c->out, msg, strlen(msg)); - for (i = strlen(msg); i < c->sx; i++) - input_store8(c->out, ' '); + memset(msg + size, SCREEN_DEFDATA, (c->sx - 1) - size); + } + screen_draw_write_string(&ctx, "%s", msg); xfree(msg); - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); + buffer_flush(c->tty.fd, c->tty.in, c->tty.out); + usleep(750000); - hdr.type = MSG_PAUSE; - hdr.size = 0; - buffer_write(c->out, &hdr, sizeof hdr); - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_stop(&ctx); - if (status_lines == 0) - window_draw(w, c->out, c->sy - 1, 1); - else - status_write(c); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); + if (status_lines == 0) { + window_draw(c->session->curw->window, &ctx, c->sy - 1, 1); + screen_draw_stop(&ctx); + } else { + screen_draw_stop(&ctx); + status_write_client(c); + } } diff --git a/server-msg.c b/server-msg.c index 471f1f10..afa947bb 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,5 @@ -/* $Id: server-msg.c,v 1.37 2007-11-24 20:08:49 nicm Exp $ */ + +/* $Id: server-msg.c,v 1.38 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -18,6 +19,7 @@ #include +#include #include #include #include @@ -26,7 +28,6 @@ int server_msg_fn_command(struct hdr *, struct client *); int server_msg_fn_identify(struct hdr *, struct client *); -int server_msg_fn_keys(struct hdr *, struct client *); int server_msg_fn_resize(struct hdr *, struct client *); void printflike2 server_msg_fn_command_error( @@ -43,7 +44,6 @@ const struct server_msg server_msg_table[] = { { MSG_IDENTIFY, server_msg_fn_identify }, { MSG_COMMAND, server_msg_fn_command }, { MSG_RESIZE, server_msg_fn_resize }, - { MSG_KEYS, server_msg_fn_keys }, }; #define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0]) @@ -152,7 +152,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) for (i = 0; i < ARRAY_LENGTH(&clients); i++) { /* XXX fnmatch, multi clients etc */ c = ARRAY_ITEM(&clients, i); - if (c != NULL && strcmp(client, c->tty) == 0) + if (c != NULL && strcmp(client, c->tty.path) == 0) ctx.client = c; } if (ctx.client == NULL) { @@ -192,10 +192,12 @@ int server_msg_fn_identify(struct hdr *hdr, struct client *c) { struct msg_identify_data data; + char *term; if (hdr->size < sizeof data) fatalx("bad MSG_IDENTIFY size"); buffer_read(c->in, &data, sizeof data); + term = cmd_recv_string(c->in); log_debug("identify msg from client: %u,%u", data.sx, data.sy); @@ -203,7 +205,8 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c) c->sy = data.sy; data.tty[(sizeof data.tty) - 1] = '\0'; - c->tty = xstrdup(data.tty); + tty_init(&c->tty, data.tty, xstrdup(term)); + xfree(term); c->flags |= CLIENT_TERMINAL; @@ -235,34 +238,3 @@ server_msg_fn_resize(struct hdr *hdr, struct client *c) return (0); } - -int -server_msg_fn_keys(struct hdr *hdr, struct client *c) -{ - struct window *w = c->session->curw->window; - int key; - size_t size; - - if (hdr->size & 0x1) - fatalx("bad MSG_KEYS size"); - - size = hdr->size; - while (size != 0) { - key = (int16_t) input_extract16(c->in); - size -= 2; - - if (c->flags & CLIENT_PREFIX) { - key_bindings_dispatch(key, c); - c->flags &= ~CLIENT_PREFIX; - continue; - } - - if (key == prefix_key) { - c->flags |= CLIENT_PREFIX; - continue; - } - window_key(w, key); - } - - return (0); -} diff --git a/server.c b/server.c index f71d6d1d..390d122f 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.39 2007-11-21 13:11:41 nicm Exp $ */ +/* $Id: server.c,v 1.40 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -49,6 +49,7 @@ void server_handle_windows(struct pollfd **); void server_fill_clients(struct pollfd **); void server_handle_clients(struct pollfd **); struct client *server_accept_client(int); +void server_handle_client(struct client *); void server_handle_window(struct window *); void server_lost_client(struct client *); void server_lost_window(struct window *); @@ -139,7 +140,7 @@ server_main(const char *srv_path, int srv_fd) pfds = NULL; while (!sigterm) { /* Initialise pollfd array. */ - nfds = 1 + ARRAY_LENGTH(&windows) + ARRAY_LENGTH(&clients); + nfds = 1 + ARRAY_LENGTH(&windows) + ARRAY_LENGTH(&clients) * 2; pfds = xrealloc(pfds, nfds, sizeof *pfds); pfd = pfds; @@ -246,7 +247,9 @@ server_fill_clients(struct pollfd **pfd) u_int i; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if ((c = ARRAY_ITEM(&clients, i)) == NULL) + c = ARRAY_ITEM(&clients, i); + + if (c == NULL) (*pfd)->fd = -1; else { (*pfd)->fd = c->fd; @@ -255,6 +258,16 @@ server_fill_clients(struct pollfd **pfd) (*pfd)->events |= POLLOUT; } (*pfd)++; + + if (c == NULL || c->tty.fd == -1) + (*pfd)->fd = -1; + else { + (*pfd)->fd = c->tty.fd; + (*pfd)->events = POLLIN; + if (BUFFER_USED(c->tty.out) > 0) + (*pfd)->events |= POLLOUT; + } + (*pfd)++; } } @@ -266,11 +279,23 @@ server_handle_clients(struct pollfd **pfd) u_int i; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if ((c = ARRAY_ITEM(&clients, i)) != NULL) { - if (buffer_poll(*pfd, c->in, c->out) != 0) + c = ARRAY_ITEM(&clients, i); + + if (c != NULL) { + if (buffer_poll(*pfd, c->in, c->out) != 0) { + server_lost_client(c); + (*pfd) += 2; + continue; + } else + server_msg_dispatch(c); + } + (*pfd)++; + + if (c != NULL && c->tty.fd != -1) { + if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0) server_lost_client(c); else - server_msg_dispatch(c); + server_handle_client(c); } (*pfd)++; } @@ -302,6 +327,8 @@ server_accept_client(int srv_fd) c->in = buffer_create(BUFSIZ); c->out = buffer_create(BUFSIZ); + c->tty.fd = -1; + c->session = NULL; c->sx = 80; c->sy = 25; @@ -316,6 +343,25 @@ server_accept_client(int srv_fd) return (c); } +/* Input data from client. */ +void +server_handle_client(struct client *c) +{ + struct window *w = c->session->curw->window; + int key; + + while (tty_keys_next(&c->tty, &key) == 0) { + if (c->flags & CLIENT_PREFIX) { + key_bindings_dispatch(key, c); + c->flags &= ~CLIENT_PREFIX; + continue; + } else if (key == prefix_key) + c->flags |= CLIENT_PREFIX; + else + window_key(w, key); + } +} + /* Lost a client. */ void server_lost_client(struct client *c) @@ -327,8 +373,8 @@ server_lost_client(struct client *c) ARRAY_SET(&clients, i, NULL); } - if (c->tty != NULL) - xfree(c->tty); + tty_free(&c->tty); + close(c->fd); buffer_destroy(c->in); buffer_destroy(c->out); @@ -341,17 +387,10 @@ server_lost_client(struct client *c) void server_handle_window(struct window *w) { - struct buffer *b; struct session *s; u_int i; - b = buffer_create(BUFSIZ); - window_parse(w, b); - if (BUFFER_USED(b) != 0) { - server_write_window_cur( - w, MSG_DATA, BUFFER_OUT(b), BUFFER_USED(b)); - } - buffer_destroy(b); + window_parse(w); if (!(w->flags & WINDOW_BELL)) return; @@ -364,17 +403,17 @@ server_handle_window(struct window *w) switch (bell_action) { case BELL_ANY: - server_write_window_all(w, MSG_DATA, "\007", 1); + tty_write_window(w, TTY_CHARACTER, '\007'); break; case BELL_CURRENT: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); if (s != NULL && s->curw->window == w) - server_write_session(s, MSG_DATA, "\007", 1); + tty_write_session(s, TTY_CHARACTER, '\007'); } break; } - server_status_window_all(w); + server_status_window(w); w->flags &= ~WINDOW_BELL; } diff --git a/status.c b/status.c index 15821313..f6b0a057 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.13 2007-11-22 18:09:43 nicm Exp $ */ +/* $Id: status.c,v 1.14 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,19 +25,19 @@ void printflike3 status_print(struct buffer *, size_t *, const char *, ...); void -status_write(struct client *c) +status_write_client(struct client *c) { - struct screen *s = &c->session->curw->window->screen; - struct buffer *b = c->out; - struct winlink *wl; - size_t size; - char flag; + struct screen_draw_ctx ctx; + struct winlink *wl; + char flag; - input_store_zero(b, CODE_CURSOROFF); - input_store_two(b, CODE_CURSORMOVE, c->sy - status_lines + 1, 1); - input_store_two(b, CODE_ATTRIBUTES, 0, status_colour); + if (status_lines == 0 || c->sy <= status_lines) + return; + + screen_draw_start_client(&ctx, c, 0, 0); + screen_draw_move_cursor(&ctx, 0, c->sy - status_lines); + screen_draw_set_attributes(&ctx, 0, status_colour); - size = c->sx; RB_FOREACH(wl, winlinks, &c->session->windows) { flag = ' '; if (wl == c->session->lastw) @@ -46,45 +46,50 @@ status_write(struct client *c) flag = '*'; if (session_hasbell(c->session, wl)) flag = '!'; - status_print( - b, &size, "%d:%s%c ", wl->idx, wl->window->name, flag); + screen_draw_write_string( + &ctx, "%d:%s%c ", wl->idx, wl->window->name, flag); - if (size == 0) + if (ctx.cx >= screen_last_x(ctx.s)) break; } - while (size-- > 0) - input_store8(b, ' '); + screen_draw_clear_line_to(&ctx, screen_last_x(ctx.s)); - input_store_two(b, CODE_ATTRIBUTES, s->attr, s->colr); - input_store_two(b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); - if (s->mode & MODE_BACKGROUND) { - if (s->mode & MODE_BGCURSOR) - input_store_zero(c->out, CODE_CURSORON); - } else { - if (s->mode & MODE_CURSOR) - input_store_zero(c->out, CODE_CURSORON); - } + screen_draw_stop(&ctx); } -void printflike3 -status_print(struct buffer *b, size_t *size, const char *fmt, ...) +void +status_write_window(struct window *w) { - va_list ap; - char *msg, *ptr; - int n; + struct client *c; + u_int i; - va_start(ap, fmt); - n = xvasprintf(&msg, fmt, ap); - va_end(ap); + if (w->screen.mode & MODE_HIDDEN) + return; - if ((size_t) n > *size) { - msg[*size] = '\0'; - n = *size; + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session == NULL) + continue; + if (c->session->curw->window != w) + continue; + + status_write_client(c); + } +} + +void +status_write_session(struct session *s) +{ + struct client *c; + u_int i; + + if (s->flags & SESSION_UNATTACHED) + return; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session != s) + continue; + status_write_client(c); } - - for (ptr = msg; *ptr != '\0'; ptr++) - input_store8(b, *ptr); - (*size) -= n; - - xfree(msg); } diff --git a/tmux.h b/tmux.h index c9ad0d6b..4cc44694 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.100 2007-11-24 23:29:49 nicm Exp $ */ +/* $Id: tmux.h,v 1.101 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -41,6 +41,7 @@ #include #include #include +#include #include "array.h" @@ -255,34 +256,32 @@ struct buffer { #define KEYC_UP -149 #define KEYC_MOUSE -150 -/* Translated escape codes. */ -#define CODE_CURSORUP 0 -#define CODE_CURSORDOWN 1 -#define CODE_CURSORRIGHT 2 -#define CODE_CURSORLEFT 3 -#define CODE_INSERTCHARACTER 4 -#define CODE_DELETECHARACTER 5 -#define CODE_INSERTLINE 6 -#define CODE_DELETELINE 7 -#define CODE_CLEARLINE 8 -/* 9 unused */ -/* 10 unused */ -#define CODE_CLEARENDOFLINE 11 -#define CODE_CLEARSTARTOFLINE 12 -#define CODE_CURSORMOVE 13 -#define CODE_ATTRIBUTES 14 -#define CODE_CURSOROFF 15 -#define CODE_CURSORON 16 -#define CODE_REVERSEINDEX 17 -/* 18 unused */ -#define CODE_SCROLLREGION 19 -#define CODE_INSERTON 20 -#define CODE_INSERTOFF 21 -#define CODE_KCURSOROFF 22 -#define CODE_KCURSORON 23 -#define CODE_KKEYPADOFF 24 -#define CODE_KKEYPADON 25 -#define CODE_TITLE 26 +/* Output codes. */ +#define TTY_CHARACTER 0 +#define TTY_CURSORUP 1 +#define TTY_CURSORDOWN 2 +#define TTY_CURSORRIGHT 3 +#define TTY_CURSORLEFT 4 +#define TTY_INSERTCHARACTER 5 +#define TTY_DELETECHARACTER 6 +#define TTY_INSERTLINE 7 +#define TTY_DELETELINE 8 +#define TTY_CLEARLINE 9 +#define TTY_CLEARENDOFLINE 10 +#define TTY_CLEARSTARTOFLINE 11 +#define TTY_CURSORMOVE 12 +#define TTY_ATTRIBUTES 13 +#define TTY_CURSOROFF 14 +#define TTY_CURSORON 15 +#define TTY_REVERSEINDEX 16 +#define TTY_SCROLLREGION 17 +#define TTY_INSERTON 18 +#define TTY_INSERTOFF 19 +#define TTY_KCURSOROFF 20 +#define TTY_KCURSORON 21 +#define TTY_KKEYPADOFF 22 +#define TTY_KKEYPADON 23 +#define TTY_TITLE 24 /* Message codes. */ enum hdrtype { @@ -294,9 +293,6 @@ enum hdrtype { MSG_READY, MSG_DETACH, MSG_RESIZE, - MSG_DATA, - MSG_KEYS, - MSG_PAUSE, }; /* Message header structure. */ @@ -317,6 +313,8 @@ struct msg_identify_data { u_int sx; u_int sy; + + size_t termlen; }; struct msg_resize_data { @@ -394,8 +392,10 @@ struct screen_draw_sel { /* Screen redraw context. */ struct screen_draw_ctx { + void *data; + void (*write)(void *, int, ...); + struct screen *s; - struct buffer *b; u_int cx; u_int cy; @@ -423,8 +423,6 @@ struct screen_draw_ctx { #define screen_in_y(s, y) ((y) < screen_size_y(s)) #define screen_in_region(s, y) ((y) >= (s)->rupper && (y) <= (s)->rlower) -#define screen_hidden(s) ((s)->mode & (MODE_HIDDEN|MODE_BACKGROUND)) - /* Screen default contents. */ #define SCREEN_DEFDATA ' ' #define SCREEN_DEFATTR 0 @@ -439,7 +437,6 @@ struct input_arg { /* Input parser context. */ struct input_ctx { struct window *w; - struct buffer *b; u_char *buf; size_t len; @@ -462,7 +459,8 @@ struct input_ctx { struct window_mode { void (*init)(struct window *); void (*resize)(struct window *, u_int, u_int); - void (*draw)(struct window *, struct buffer *, u_int, u_int); + void (*draw)( + struct window *, struct screen_draw_ctx *, u_int, u_int); void (*key)(struct window *, int); }; @@ -516,19 +514,49 @@ struct session { }; ARRAY_DECL(sessions, struct session *); -/* Client connection. */ -struct client { - char *tty; +/* TTY information. */ +struct tty_key { + int code; + char *string; + + RB_ENTRY(tty_key) entry; +}; + +struct tty { + char *path; + + char *term; + TERMINAL *termp; int fd; struct buffer *in; struct buffer *out; + struct termios tio; + + u_int attr; + u_int colr; + + u_char acs[UCHAR_MAX + 1]; + + size_t ksize; /* maximum key size */ + RB_HEAD(tty_keys, tty_key) ktree; +}; + +/* Client connection. */ +struct client { + int fd; + struct buffer *in; + struct buffer *out; + + struct tty tty; + u_int sx; u_int sy; #define CLIENT_TERMINAL 0x1 #define CLIENT_PREFIX 0x2 +#define CLIENT_ATTACHED 0x4 int flags; struct session *session; @@ -541,13 +569,8 @@ struct client_ctx { struct buffer *srv_in; struct buffer *srv_out; - int loc_fd; - struct buffer *loc_in; - struct buffer *loc_out; - -#define CCTX_PAUSE 0x1 -#define CCTX_DETACH 0x2 -#define CCTX_EXIT 0x4 +#define CCTX_DETACH 0x1 +#define CCTX_EXIT 0x2 int flags; }; @@ -629,6 +652,28 @@ void logfile(const char *); void siginit(void); void sigreset(void); +/* tty.c */ +void tty_init(struct tty *, char *, char *); +int tty_open(struct tty *, char **); +void tty_close(struct tty *); +void tty_free(struct tty *); +void tty_vwrite(struct tty *, int, va_list); + +/* tty-keys.c */ +int tty_keys_cmp(struct tty_key *, struct tty_key *); +RB_PROTOTYPE(tty_keys, tty_key, entry, tty_keys_cmp); +void tty_keys_init(struct tty *); +void tty_keys_free(struct tty *); +int tty_keys_next(struct tty *, int *); + +/* tty-write.c */ +void tty_write_client(void *, int, ...); +void tty_vwrite_client(void *, int, va_list); +void tty_write_window(void *, int, ...); +void tty_vwrite_window(void *, int, va_list); +void tty_write_session(void *, int, ...); +void tty_vwrite_session(void *, int, va_list); + /* cmd.c */ struct cmd *cmd_parse(int, char **, char **); void cmd_exec(struct cmd *, struct cmd_ctx *); @@ -708,25 +753,23 @@ void server_write_client( struct client *, enum hdrtype, const void *, size_t); void server_write_session( struct session *, enum hdrtype, const void *, size_t); -void server_write_window_cur( +void server_write_window( struct window *, enum hdrtype, const void *, size_t); -void server_write_window_all( - struct window *, enum hdrtype, const void *, size_t); -void server_status_client(struct client *); void server_clear_client(struct client *); void server_redraw_client(struct client *); -void server_status_session(struct session *); +void server_status_client(struct client *); +void server_clear_session(struct session *); void server_redraw_session(struct session *); -void server_status_window_cur(struct window *); -void server_status_window_all(struct window *); -void server_clear_window_cur(struct window *); -void server_clear_window_all(struct window *); -void server_redraw_window_cur(struct window *); -void server_redraw_window_all(struct window *); +void server_status_session(struct session *); +void server_clear_window(struct window *); +void server_redraw_window(struct window *); +void server_status_window(struct window *); void printflike2 server_write_message(struct client *, const char *, ...); /* status.c */ -void status_write(struct client *c); +void status_write_client(struct client *); +void status_write_session(struct session *); +void status_write_window(struct window *); /* resize.c */ void recalculate_sizes(void); @@ -734,17 +777,10 @@ void recalculate_sizes(void); /* input.c */ void input_init(struct window *); void input_free(struct window *); -void input_parse(struct window *, struct buffer *); -uint8_t input_extract8(struct buffer *); -uint16_t input_extract16(struct buffer *); -void input_store8(struct buffer *, uint8_t); -void input_store16(struct buffer *, uint16_t); -void input_store_zero(struct buffer *, u_char); -void input_store_one(struct buffer *, u_char, uint16_t); -void input_store_two(struct buffer *, u_char, uint16_t, uint16_t); +void input_parse(struct window *); /* input-key.c */ -void input_key(struct buffer *, int); +void input_key(struct window *, int); /* screen-display.c */ void screen_display_make_lines(struct screen *, u_int, u_int); @@ -788,15 +824,29 @@ void screen_reduce_line(struct screen *, u_int, u_int); void screen_get_cell( struct screen *, u_int, u_int, u_char *, u_char *, u_char *); void screen_set_cell(struct screen *, u_int, u_int, u_char, u_char, u_char); -void screen_draw_start(struct screen_draw_ctx *, - struct screen *, struct buffer *, u_int, u_int); +void screen_draw_start_window( + struct screen_draw_ctx *, struct window *, u_int, u_int); +void screen_draw_start_client( + struct screen_draw_ctx *, struct client *, u_int, u_int); +void screen_draw_start_session( + struct screen_draw_ctx *, struct session *, u_int, u_int); +void screen_draw_start(struct screen_draw_ctx *, struct screen *s, + void (*)(void *, int, ...), void *, u_int, u_int); void screen_draw_stop(struct screen_draw_ctx *); void screen_draw_set_selection( struct screen_draw_ctx *, int, u_int, u_int, u_int, u_int); int screen_draw_check_selection(struct screen_draw_ctx *, u_int, u_int); void screen_draw_get_cell(struct screen_draw_ctx *, u_int, u_int, u_char *, u_char *, u_char *); -void screen_draw_move(struct screen_draw_ctx *, u_int, u_int); +void screen_draw_insert_characters(struct screen_draw_ctx *, u_int); +void screen_draw_delete_characters(struct screen_draw_ctx *, u_int); +void screen_draw_insert_lines(struct screen_draw_ctx *, u_int); +void screen_draw_delete_lines(struct screen_draw_ctx *, u_int); +void screen_draw_clear_line_to(struct screen_draw_ctx *, u_int); +void screen_draw_clear_screen(struct screen_draw_ctx *); +void printflike2 screen_draw_write_string( + struct screen_draw_ctx *, const char *, ...); +void screen_draw_move_cursor(struct screen_draw_ctx *, u_int, u_int); void screen_draw_set_attributes(struct screen_draw_ctx *, u_char, u_char); void screen_draw_cell(struct screen_draw_ctx *, u_int, u_int); void screen_draw_cells(struct screen_draw_ctx *, u_int, u_int, u_int); @@ -812,12 +862,6 @@ void screen_fill_lines( void screen_fill_cells( struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); -/* local.c */ -int local_init(struct buffer **, struct buffer **); -void local_done(void); -int local_key(void); -void local_output(struct buffer *, size_t); - /* window.c */ extern struct windows windows; int window_cmp(struct window *, struct window *); @@ -835,8 +879,9 @@ struct window *window_create( const char *, const char *, const char **, u_int, u_int); void window_destroy(struct window *); int window_resize(struct window *, u_int, u_int); -void window_parse(struct window *, struct buffer *); -void window_draw(struct window *, struct buffer *, u_int, u_int); +void window_parse(struct window *); +void window_draw( + struct window *, struct screen_draw_ctx *, u_int, u_int); void window_key(struct window *, int); /* window-copy.c */ @@ -881,9 +926,14 @@ void buffer_insert_range(struct buffer *, size_t, size_t); void buffer_delete_range(struct buffer *, size_t, size_t); void buffer_write(struct buffer *, const void *, size_t); void buffer_read(struct buffer *, void *, size_t); +void buffer_write8(struct buffer *, uint8_t); +void buffer_write16(struct buffer *, uint16_t); +uint8_t buffer_read8(struct buffer *); +uint16_t buffer_read16(struct buffer *); /* buffer-poll.c */ int buffer_poll(struct pollfd *, struct buffer *, struct buffer *); +void buffer_flush(int, struct buffer *n, struct buffer *); /* log.c */ void log_open(FILE *, int, int); diff --git a/tty-keys.c b/tty-keys.c new file mode 100644 index 00000000..186bf819 --- /dev/null +++ b/tty-keys.c @@ -0,0 +1,273 @@ +/* $Id: tty-keys.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +struct { + const char *name; + int code; +} tty_keys[] = { + { "kBEG", KEYC_SBEG }, + { "kCAN", KEYC_SCANCEL }, + { "kCMD", KEYC_SCOMMAND }, + { "kCPY", KEYC_SCOPY }, + { "kCRT", KEYC_SCREATE }, + { "kDC", KEYC_SDC }, + { "kDL", KEYC_SDL }, + { "kEND", KEYC_SEND }, + { "kEOL", KEYC_SEOL }, + { "kEXT", KEYC_SEXIT }, + { "kFND", KEYC_SFIND }, + { "kHLP", KEYC_SHELP }, + { "kHOM", KEYC_SHOME }, + { "kIC", KEYC_SIC }, + { "kLFT", KEYC_SLEFT }, + { "kMOV", KEYC_SMOVE }, + { "kMSG", KEYC_SMESSAGE }, + { "kNXT", KEYC_SNEXT }, + { "kOPT", KEYC_SOPTIONS }, + { "kPRT", KEYC_SPRINT }, + { "kPRV", KEYC_SPREVIOUS }, + { "kRDO", KEYC_SREDO }, + { "kRES", KEYC_SRSUME }, + { "kRIT", KEYC_SRIGHT }, + { "kRPL", KEYC_SREPLACE }, + { "kSAV", KEYC_SSAVE }, + { "kSPD", KEYC_SSUSPEND }, + { "kUND", KEYC_SUNDO }, + { "ka1", KEYC_A1 }, + { "ka3", KEYC_A3 }, + { "kb2", KEYC_B2 }, + { "kbeg", KEYC_BEG }, + { "kc1", KEYC_C1 }, + { "kc3", KEYC_C3 }, + { "kcan", KEYC_CANCEL }, + { "kcbt", KEYC_BTAB }, + { "kclo", KEYC_CLOSE }, + { "kclr", KEYC_CLEAR }, + { "kcmd", KEYC_COMMAND }, + { "kcpy", KEYC_COPY }, + { "kcrt", KEYC_CREATE }, + { "kctab", KEYC_CTAB }, + { "kcub1", KEYC_LEFT }, + { "kcud1", KEYC_DOWN }, + { "kcuf1", KEYC_RIGHT }, + { "kcuu1", KEYC_UP }, + { "kdch1", KEYC_DC }, + { "kdl1", KEYC_DL }, + { "ked", KEYC_EOS }, + { "kel", KEYC_EOL }, + { "kend", KEYC_END }, + { "kent", KEYC_ENTER }, + { "kext", KEYC_EXIT }, + { "kf0", KEYC_F0 }, + { "kf1", KEYC_F1 }, + { "kf10", KEYC_F10 }, + { "kf11", KEYC_F11 }, + { "kf12", KEYC_F12 }, + { "kf13", KEYC_F13 }, + { "kf14", KEYC_F14 }, + { "kf15", KEYC_F15 }, + { "kf16", KEYC_F16 }, + { "kf17", KEYC_F17 }, + { "kf18", KEYC_F18 }, + { "kf19", KEYC_F19 }, + { "kf2", KEYC_F2 }, + { "kf20", KEYC_F20 }, + { "kf21", KEYC_F21 }, + { "kf22", KEYC_F22 }, + { "kf23", KEYC_F23 }, + { "kf24", KEYC_F24 }, + { "kf25", KEYC_F25 }, + { "kf26", KEYC_F26 }, + { "kf27", KEYC_F27 }, + { "kf28", KEYC_F28 }, + { "kf29", KEYC_F29 }, + { "kf3", KEYC_F3 }, + { "kf30", KEYC_F30 }, + { "kf31", KEYC_F31 }, + { "kf32", KEYC_F32 }, + { "kf33", KEYC_F33 }, + { "kf34", KEYC_F34 }, + { "kf35", KEYC_F35 }, + { "kf36", KEYC_F36 }, + { "kf37", KEYC_F37 }, + { "kf38", KEYC_F38 }, + { "kf39", KEYC_F39 }, + { "kf4", KEYC_F4 }, + { "kf40", KEYC_F40 }, + { "kf41", KEYC_F41 }, + { "kf42", KEYC_F42 }, + { "kf43", KEYC_F43 }, + { "kf44", KEYC_F44 }, + { "kf45", KEYC_F45 }, + { "kf46", KEYC_F46 }, + { "kf47", KEYC_F47 }, + { "kf48", KEYC_F48 }, + { "kf49", KEYC_F49 }, + { "kf5", KEYC_F5 }, + { "kf50", KEYC_F50 }, + { "kf51", KEYC_F51 }, + { "kf52", KEYC_F52 }, + { "kf53", KEYC_F53 }, + { "kf54", KEYC_F54 }, + { "kf55", KEYC_F55 }, + { "kf56", KEYC_F56 }, + { "kf57", KEYC_F57 }, + { "kf58", KEYC_F58 }, + { "kf59", KEYC_F59 }, + { "kf6", KEYC_F6 }, + { "kf60", KEYC_F60 }, + { "kf61", KEYC_F61 }, + { "kf62", KEYC_F62 }, + { "kf63", KEYC_F63 }, + { "kf7", KEYC_F7 }, + { "kf8", KEYC_F8 }, + { "kf9", KEYC_F9 }, + { "kfnd", KEYC_FIND }, + { "khlp", KEYC_HELP }, + { "khome", KEYC_HOME }, + { "khts", KEYC_STAB }, + { "kich1", KEYC_IC }, + { "kil1", KEYC_IL }, + { "kind", KEYC_SF }, + { "kll", KEYC_LL }, + { "kmov", KEYC_MOVE }, + { "kmrk", KEYC_MARK }, + { "kmsg", KEYC_MESSAGE }, + { "knp", KEYC_NPAGE }, + { "knxt", KEYC_NEXT }, + { "kopn", KEYC_OPEN }, + { "kopt", KEYC_OPTIONS }, + { "kpp", KEYC_PPAGE }, + { "kprt", KEYC_PRINT }, + { "kprv", KEYC_PREVIOUS }, + { "krdo", KEYC_REDO }, + { "kref", KEYC_REFERENCE }, + { "kres", KEYC_RESUME }, + { "krfr", KEYC_REFRESH }, + { "kri", KEYC_SR }, + { "krmir", KEYC_EIC }, + { "krpl", KEYC_REPLACE }, + { "krst", KEYC_RESTART }, + { "ksav", KEYC_SAVE }, + { "kslt", KEYC_SELECT }, + { "kspd", KEYC_SUSPEND }, + { "ktbc", KEYC_CATAB }, + { "kund", KEYC_UNDO }, + { "pmous", KEYC_MOUSE }, +}; +#define NTTYKEYS (sizeof tty_keys / sizeof tty_keys[0]) + +RB_GENERATE(tty_keys, tty_key, entry, tty_keys_cmp); + +int +tty_keys_cmp(struct tty_key *k1, struct tty_key *k2) +{ + return (strcmp(k1->string, k2->string)); +} + +void +tty_keys_init(struct tty *tty) +{ + struct tty_key *tk; + u_int i; + char *s; + + RB_INIT(&tty->ktree); + + tty->ksize = 0; + for (i = 0; i < NTTYKEYS; i++) { + s = tigetstr(tty_keys[i].name); + if (s == (char *) -1 || s == (char *) 0) + continue; + if (s[0] != '\e' || s[1] == '\0') + continue; + + tk = xmalloc(sizeof *tk); + tk->string = xstrdup(s + 1); + tk->code = tty_keys[i].code; + + if (strlen(tk->string) > tty->ksize) + tty->ksize = strlen(tk->string); + RB_INSERT(tty_keys, &tty->ktree, tk); + + log_debug("found key %d: size now %zu", tk->code, tty->ksize); + } +} + +void +tty_keys_free(struct tty *tty) +{ + struct tty_key *tk, *tl; + + for (tk = RB_MIN(tty_keys, &tty->ktree); tk != NULL; tk = tl) { + tl = RB_NEXT(tty_keys, &tty->ktree, tk); + RB_REMOVE(tty_keys, &tty->ktree, tk); + xfree(tk->string); + xfree(tk); + } +} + +int +tty_keys_next(struct tty *tty, int *code) +{ + struct tty_key *tk, tl; + size_t size; + char *s; + + if (BUFFER_USED(tty->in) == 0) + return (1); + log_debug("keys have %zu bytes", BUFFER_USED(tty->in)); + + if (*BUFFER_OUT(tty->in) != '\e') { + *code = buffer_read8(tty->in); + return (0); + } + + tk = NULL; + s = xmalloc(tty->ksize + 1); + for (size = tty->ksize; size > 0; size--) { + if (size >= BUFFER_USED(tty->in)) + continue; + memcpy(s, BUFFER_OUT(tty->in) + 1, size); + s[size] = '\0'; + + tl.string = s; + tk = RB_FIND(tty_keys, &tty->ktree, &tl); + if (tk != NULL) + break; + } + xfree(s); + if (tk == NULL) { + /* + * XXX Pass through unchanged. + */ + *code = '\e'; + buffer_remove(tty->in, 1); + return (0); + } + buffer_remove(tty->in, size + 1); + + *code = tk->code; + return (0); +} diff --git a/tty-write.c b/tty-write.c new file mode 100644 index 00000000..e796b3e1 --- /dev/null +++ b/tty-write.c @@ -0,0 +1,107 @@ +/* $Id: tty-write.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tmux.h" + +void +tty_write_client(void *ptr, int cmd, ...) +{ + struct client *c = ptr; + + va_list ap; + + va_start(ap, cmd); + tty_vwrite_client(c, cmd, ap); + va_end(ap); +} + +void +tty_vwrite_client(void *ptr, int cmd, va_list ap) +{ + struct client *c = ptr; + + tty_vwrite(&c->tty, cmd, ap); +} + +void +tty_write_window(void *ptr, int cmd, ...) +{ + va_list ap; + + va_start(ap, cmd); + tty_vwrite_window(ptr, cmd, ap); + va_end(ap); +} + +void +tty_vwrite_window(void *ptr, int cmd, va_list ap) +{ + struct window *w = ptr; + struct client *c; + va_list aq; + u_int i; + + if (w->screen.mode & MODE_HIDDEN) + return; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session == NULL) + continue; + if (c->session->curw->window != w) + continue; + + va_copy(aq, ap); + tty_vwrite(&c->tty, cmd, aq); + va_end(aq); + } +} + +void +tty_write_session(void *ptr, int cmd, ...) +{ + va_list ap; + + va_start(ap, cmd); + tty_vwrite_session(ptr, cmd, ap); + va_end(ap); +} + +void +tty_vwrite_session(void *ptr, int cmd, va_list ap) +{ + struct session *s = ptr; + struct client *c; + va_list aq; + u_int i; + + if (s->flags & SESSION_UNATTACHED) + return; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session != s) + continue; + + va_copy(aq, ap); + tty_vwrite(&c->tty, cmd, aq); + va_end(aq); + } +} diff --git a/tty.c b/tty.c new file mode 100644 index 00000000..636c738c --- /dev/null +++ b/tty.c @@ -0,0 +1,401 @@ +/* $Id: tty.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#define TTYDEFCHARS +/* glibc requires unistd.h before termios.h for TTYDEFCHARS. */ +#include +#include + +#include "tmux.h" + +void tty_fill_acs(struct tty *); +u_char tty_get_acs(struct tty *, u_char); + +void tty_raw(struct tty *, const char *); +void tty_puts(struct tty *, const char *); +void tty_putc(struct tty *, char); + +void tty_attributes(struct tty *, u_char, u_char); +char tty_translate(char); + +void +tty_init(struct tty *tty, char *path, char *term) +{ + tty->path = xstrdup(path); + tty->term = xstrdup(term); +} + +int +tty_open(struct tty *tty, char **cause) +{ + struct termios tio; + int error; + + tty->fd = open(tty->path, O_RDWR|O_NONBLOCK); + if (tty->fd == -1) { + xasprintf(cause, "%s: %s", tty->path, strerror(errno)); + return (-1); + } + + if (tty->term == NULL) + tty->term = xstrdup("unknown"); + if (setupterm(tty->term, tty->fd, &error) != OK) { + switch (error) { + case 0: + xasprintf(cause, "can't use hardcopy terminal"); + break; + case 1: + xasprintf(cause, "missing or unsuitable terminal"); + break; + case 2: + xasprintf(cause, "can't find terminfo database"); + break; + default: + xasprintf(cause, "unknown error"); + } + return (-1); + } + tty->termp = cur_term; + + tty->in = buffer_create(BUFSIZ); + tty->out = buffer_create(BUFSIZ); + + tty->attr = SCREEN_DEFATTR; + tty->colr = SCREEN_DEFCOLR; + + tty_keys_init(tty); + + tty_fill_acs(tty); + + if (tcgetattr(tty->fd, &tty->tio) != 0) + fatal("tcgetattr failed"); + memset(&tio, 0, sizeof tio); + tio.c_iflag = TTYDEF_IFLAG & ~(IXON|IXOFF|ICRNL|INLCR); + tio.c_oflag = TTYDEF_OFLAG & ~(OPOST|ONLCR|OCRNL|ONLRET); + tio.c_lflag = + TTYDEF_LFLAG & ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG); + tio.c_cflag = TTYDEF_CFLAG; + memcpy(&tio.c_cc, ttydefchars, sizeof tio.c_cc); + cfsetspeed(&tio, TTYDEF_SPEED); + if (tcsetattr(tty->fd, TCSANOW, &tio) != 0) + fatal("tcsetattr failed"); + + if (enter_ca_mode != NULL) + tty_puts(tty, enter_ca_mode); + if (keypad_xmit != NULL) + tty_puts(tty, keypad_xmit); + if (ena_acs != NULL) + tty_puts(tty, ena_acs); + tty_puts(tty, clear_screen); + + return (0); +} + +void +tty_close(struct tty *tty) +{ + struct winsize ws; + + if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) + fatal("ioctl(TIOCGWINSZ)"); + + if (keypad_local != NULL) + tty_raw(tty, keypad_local); + if (exit_ca_mode != NULL) + tty_raw(tty, exit_ca_mode); + tty_raw(tty, clear_screen); + if (cursor_normal != NULL) + tty_raw(tty, cursor_normal); + if (exit_attribute_mode != NULL) + tty_raw(tty, exit_attribute_mode); + if (change_scroll_region != NULL) + tty_raw(tty, tparm(change_scroll_region, 0, ws.ws_row - 1)); + + if (tcsetattr(tty->fd, TCSANOW, &tty->tio) != 0) + fatal("tcsetattr failed"); + del_curterm(tty->termp); + + tty_keys_free(tty); + + close(tty->fd); + buffer_destroy(tty->in); + buffer_destroy(tty->out); +} + +void +tty_free(struct tty *tty) +{ + if (tty->fd != -1) + tty_close(tty); + + if (tty->path != NULL) + xfree(tty->path); + if (tty->term != NULL) + xfree(tty->term); +} + +void +tty_fill_acs(struct tty *tty) +{ + char *ptr; + + memset(tty->acs, 0, sizeof tty->acs); + if (acs_chars == NULL || (strlen(acs_chars) % 2) != 0) + return; + for (ptr = acs_chars; *ptr != '\0'; ptr += 2) + tty->acs[(u_char) ptr[0]] = ptr[1]; +} + +u_char +tty_get_acs(struct tty *tty, u_char ch) +{ + if (tty->acs[ch] != '\0') + return (tty->acs[ch]); + return (ch); +} + +void +tty_raw(struct tty *tty, const char *s) +{ + write(tty->fd, s, strlen(s)); +} + +void +tty_puts(struct tty *tty, const char *s) +{ + buffer_write(tty->out, s, strlen(s)); +} + +void +tty_putc(struct tty *tty, char ch) +{ + if (tty->attr & ATTR_DRAWING) + ch = tty_get_acs(tty, ch); + buffer_write8(tty->out, ch); +} + +void +tty_vwrite(struct tty *tty, int cmd, va_list ap) +{ + char ch; + u_int ua, ub; + + set_curterm(tty->termp); + + switch (cmd) { + case TTY_CHARACTER: + ch = va_arg(ap, int); + switch (ch) { + case '\n': /* LF */ + tty_puts(tty, cursor_down); + break; + case '\r': /* CR */ + tty_puts(tty, carriage_return); + break; + case '\007': /* BEL */ + if (bell != NULL) + tty_puts(tty, bell); + break; + case '\010': /* BS */ + tty_puts(tty, cursor_left); + break; + default: + tty_putc(tty, ch); + break; + } + break; + case TTY_CURSORUP: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_up_cursor, ua)); + break; + case TTY_CURSORDOWN: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_down_cursor, ua)); + break; + case TTY_CURSORRIGHT: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_right_cursor, ua)); + break; + case TTY_CURSORLEFT: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_left_cursor, ua)); + break; + case TTY_CURSORMOVE: + ua = va_arg(ap, u_int); + ub = va_arg(ap, u_int); + tty_puts(tty, tparm(cursor_address, ua, ub)); + break; + case TTY_CLEARENDOFLINE: + tty_puts(tty, clr_eol); + break; + case TTY_CLEARSTARTOFLINE: + tty_puts(tty, clr_bol); + break; + case TTY_CLEARLINE: + tty_puts(tty, clr_eol); /* XXX */ + break; + case TTY_INSERTLINE: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_insert_line, ua)); + break; + case TTY_DELETELINE: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_delete_line, ua)); + break; + case TTY_INSERTCHARACTER: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_ich, ua)); + break; + case TTY_DELETECHARACTER: + ua = va_arg(ap, u_int); + tty_puts(tty, tparm(parm_dch, ua)); + break; + case TTY_CURSORON: + if (cursor_normal != NULL) + tty_puts(tty, cursor_normal); + break; + case TTY_CURSOROFF: + if (cursor_invisible != NULL) + tty_puts(tty, cursor_invisible); + break; + case TTY_REVERSEINDEX: + tty_puts(tty, scroll_reverse); + break; + case TTY_SCROLLREGION: + ua = va_arg(ap, u_int); + ub = va_arg(ap, u_int); + tty_puts(tty, tparm(change_scroll_region, ua, ub)); + break; + case TTY_INSERTON: + if (enter_insert_mode != NULL) + tty_puts(tty, enter_insert_mode); + break; + case TTY_INSERTOFF: + if (exit_insert_mode != NULL) + tty_puts(tty, exit_insert_mode); + break; +#if 0 + case TTY_KCURSOROFF: + t = tigetstr("CE"); + if (t != (char *) 0 && t != (char *) -1) + tty_puts(tty, t); + break; + case TTY_KCURSORON: + t = tigetstr("CS"); + if (t != (char *) 0 && t != (char *) -1) + tty_puts(tty, t); + break; + case TTY_KKEYPADOFF: + if (keypad_local != NULL) + tty_puts(tty, keypad_local); + break; + case TTY_KKEYPADON: + if (keypad_xmit != NULL) + tty_puts(tty, keypad_xmit); +#endif + break; + case TTY_TITLE: + break; + case TTY_ATTRIBUTES: + ua = va_arg(ap, u_int); + ub = va_arg(ap, u_int); + tty_attributes(tty, ua, ub); + break; + } +} + +void +tty_attributes(struct tty *tty, u_char attr, u_char colr) +{ + u_char fg, bg; + + if (attr == tty->attr && colr == tty->colr) + return; + + /* If any bits are being cleared, reset everything. */ + if (tty->attr & ~attr) { + if ((tty->attr & ATTR_DRAWING) && + exit_alt_charset_mode != NULL) + tty_puts(tty, exit_alt_charset_mode); + tty_puts(tty, exit_attribute_mode); + tty->colr = 0x88; + tty->attr = 0; + } + + /* Filter out bits already set. */ + attr &= ~tty->attr; + tty->attr |= attr; + + if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL) + tty_puts(tty, enter_bold_mode); + if ((attr & ATTR_DIM) && enter_dim_mode != NULL) + tty_puts(tty, enter_dim_mode); + if ((attr & ATTR_ITALICS) && enter_standout_mode != NULL) + tty_puts(tty, enter_standout_mode); + if ((attr & ATTR_UNDERSCORE) && enter_underline_mode != NULL) + tty_puts(tty, enter_underline_mode); + if ((attr & ATTR_BLINK) && enter_blink_mode != NULL) + tty_puts(tty, enter_blink_mode); + if ((attr & ATTR_REVERSE) && enter_reverse_mode != NULL) + tty_puts(tty, enter_reverse_mode); + if ((attr & ATTR_HIDDEN) && enter_secure_mode != NULL) + tty_puts(tty, enter_secure_mode); + if ((attr & ATTR_DRAWING) && enter_alt_charset_mode != NULL) + tty_puts(tty, enter_alt_charset_mode); + + fg = (colr >> 4) & 0xf; + if (fg != ((tty->colr >> 4) & 0xf)) { + if (tigetflag("AX") == TRUE) { + if (fg == 7) + fg = 8; + } else { + if (fg == 8) + fg = 7; + } + + if (fg == 8) + tty_puts(tty, "\e[39m"); + else if (set_a_foreground != NULL) + tty_puts(tty, tparm(set_a_foreground, fg)); + } + + bg = colr & 0xf; + if (bg != (tty->colr & 0xf)) { + if (tigetflag("AX") == TRUE) { + if (bg == 0) + bg = 8; + } else { + if (bg == 8) + bg = 0; + } + + if (bg == 8) + tty_puts(tty, "\e[49m"); + else if (set_a_background != NULL) + tty_puts(tty, tparm(set_a_background, bg)); + } + + tty->colr = colr; +} diff --git a/window-copy.c b/window-copy.c index 9b137c45..1840914c 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.9 2007-11-26 20:57:54 nicm Exp $ */ +/* $Id: window-copy.c,v 1.10 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -24,7 +24,8 @@ void window_copy_init(struct window *); void window_copy_resize(struct window *, u_int, u_int); -void window_copy_draw(struct window *, struct buffer *, u_int, u_int); +void window_copy_draw( + struct window *, struct screen_draw_ctx *, u_int, u_int); void window_copy_key(struct window *, int); void window_copy_draw_position(struct window *, struct screen_draw_ctx *); @@ -103,37 +104,32 @@ window_copy_draw_position(struct window *w, struct screen_draw_ctx *ctx) screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len); - screen_draw_move(ctx, screen_size_x(ctx->s) - len, 0); + screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); screen_draw_set_attributes(ctx, 0, status_colour); - buffer_write(ctx->b, ptr, len); + screen_draw_write_string(ctx, "%s", ptr); } void -window_copy_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +window_copy_draw( + struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) { struct window_copy_mode_data *data = w->modedata; struct screen *s = &w->screen; - struct screen_draw_ctx ctx; if (s->hsize != data->size) { data->oy += s->hsize - data->size; data->size = s->hsize; } - screen_draw_start(&ctx, s, b, data->ox, data->oy); - screen_draw_set_selection(&ctx, data->selflag, data->selx, data->sely, - data->cx + data->ox, data->size + data->cy - data->oy); if (py != 0) - screen_draw_lines(&ctx, py, ny); - else if (ny > 1) - screen_draw_lines(&ctx, py + 1, ny - 1); + screen_draw_lines(ctx, py, ny); + else { + if (ny > 1) + screen_draw_lines(ctx, py + 1, ny - 1); + window_copy_draw_position(w, ctx); + } - if (py == 0) - window_copy_draw_position(w, &ctx); - - screen_draw_stop(&ctx); - - input_store_two(b, CODE_CURSORMOVE, data->cy + 1, data->cx + 1); + window_copy_move_cursor(w); } void @@ -205,7 +201,7 @@ window_copy_key(struct window *w, int key) return; } if (data->oy != oy) { - server_redraw_window_all(w); + server_redraw_window(w); window_copy_move_cursor(w); } return; @@ -217,7 +213,7 @@ done: w->screen.mode &= ~MODE_BACKGROUND; recalculate_sizes(); - server_redraw_window_all(w); + server_redraw_window(w); } void @@ -322,30 +318,8 @@ void window_copy_move_cursor(struct window *w) { struct window_copy_mode_data *data = w->modedata; - struct client *c; - u_int i; - struct hdr hdr; - size_t size; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - input_store_two( - c->out, CODE_CURSORMOVE, data->cy + 1, data->cx + 1); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + tty_write_window(w, TTY_CURSORMOVE, data->cy, data->cx); } void @@ -467,94 +441,47 @@ window_copy_cursor_down(struct window *w) void window_copy_draw_lines(struct window *w, u_int py, u_int ny) { - struct client *c; - struct buffer *b; - u_int i; - struct hdr hdr; - size_t size; + struct window_copy_mode_data *data = w->modedata; + struct screen_draw_ctx ctx; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - b = c->out; - - buffer_ensure(b, sizeof hdr); - buffer_add(b, sizeof hdr); - size = BUFFER_USED(b); - - window_copy_draw(w, b, py, ny); - - size = BUFFER_USED(b) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(b) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + window_copy_draw(w, &ctx, py, ny); + screen_draw_stop(&ctx); } void window_copy_scroll_left(struct window *w, u_int nx) { struct window_copy_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - struct buffer *b; - u_int i, j; - struct hdr hdr; - size_t size; + u_int i; if (data->ox > SHRT_MAX - nx) nx = SHRT_MAX - data->ox; if (nx == 0) return; data->ox += nx; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - b = c->out; - - buffer_ensure(b, sizeof hdr); - buffer_add(b, sizeof hdr); - size = BUFFER_USED(b); - - screen_draw_start(&ctx, s, b, data->ox, data->oy); - screen_draw_set_selection(&ctx, - data->selflag, data->selx, data->sely, - data->cx + data->ox, data->size + data->cy - data->oy); - for (j = 1; j < screen_size_y(s); j++) { - screen_draw_move(&ctx, 0, j); - input_store_one(b, CODE_DELETECHARACTER, nx); - } - for (j = 0; j < nx; j++) - screen_draw_column(&ctx, screen_last_x(s) - j); - window_copy_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(b) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(b) - size - sizeof hdr, &hdr, sizeof hdr); - } + + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_set_selection(&ctx, + data->selflag, data->selx, data->sely, + data->cx + data->ox, data->size + data->cy - data->oy); + for (i = 1; i < screen_size_y(&w->screen); i++) { + screen_draw_move_cursor(&ctx, 0, i); + screen_draw_delete_characters(&ctx, nx); + } + for (i = 0; i < nx; i++) + screen_draw_column(&ctx, screen_last_x(&w->screen) - i); + window_copy_draw_position(w, &ctx); + screen_draw_stop(&ctx); } void window_copy_scroll_right(struct window *w, u_int nx) { struct window_copy_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - struct buffer *b; - u_int i, j; - struct hdr hdr; - size_t size; + u_int i; if (data->ox < nx) nx = data->ox; @@ -562,48 +489,26 @@ window_copy_scroll_right(struct window *w, u_int nx) return; data->ox -= nx; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - b = c->out; - - buffer_ensure(b, sizeof hdr); - buffer_add(b, sizeof hdr); - size = BUFFER_USED(b); - - screen_draw_start(&ctx, s, b, data->ox, data->oy); - screen_draw_set_selection(&ctx, - data->selflag, data->selx, data->sely, - data->cx + data->ox, data->size + data->cy - data->oy); - for (j = 1; j < screen_size_y(s); j++) { - screen_draw_move(&ctx, 0, j); - input_store_one(b, CODE_INSERTCHARACTER, nx); - } - for (j = 0; j < nx; j++) - screen_draw_column(&ctx, j); - window_copy_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(b) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(b) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_set_selection(&ctx, + data->selflag, data->selx, data->sely, + data->cx + data->ox, data->size + data->cy - data->oy); + for (i = 1; i < screen_size_y(&w->screen); i++) { + screen_draw_move_cursor(&ctx, 0, i); + screen_draw_insert_characters(&ctx, nx); + } + for (i = 0; i < nx; i++) + screen_draw_column(&ctx, i); + window_copy_draw_position(w, &ctx); + screen_draw_stop(&ctx); } void window_copy_scroll_up(struct window *w, u_int ny) { struct window_copy_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; u_int i; - struct hdr hdr; - size_t size; if (data->oy < ny) ny = data->oy; @@ -611,47 +516,26 @@ window_copy_scroll_up(struct window *w, u_int ny) return; data->oy -= ny; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - screen_draw_set_selection(&ctx, - data->selflag, data->selx, data->sely, - data->cx + data->ox, data->size + data->cy - data->oy); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_DELETELINE, ny); - for (i = 0; i < ny; i++) - screen_draw_line(&ctx, screen_last_y(s) - i); - if (data->selflag) - screen_draw_line(&ctx, screen_last_y(s) - ny); - window_copy_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_set_selection(&ctx, + data->selflag, data->selx, data->sely, + data->cx + data->ox, data->size + data->cy - data->oy); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_delete_lines(&ctx, ny); + for (i = 0; i < ny; i++) + screen_draw_line(&ctx, screen_last_y(&w->screen) - i); + if (data->selflag) + screen_draw_line(&ctx, screen_last_y(&w->screen) - ny); + window_copy_draw_position(w, &ctx); + screen_draw_stop(&ctx); } void window_copy_scroll_down(struct window *w, u_int ny) { struct window_copy_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; u_int i; - struct hdr hdr; - size_t size; if (ny > data->size) return; @@ -662,31 +546,14 @@ window_copy_scroll_down(struct window *w, u_int ny) return; data->oy += ny; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - screen_draw_set_selection(&ctx, - data->selflag, data->selx, data->sely, - data->cx + data->ox, data->size + data->cy - data->oy); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_INSERTLINE, ny); - for (i = 1; i < ny + 1; i++) - screen_draw_line(&ctx, i); - window_copy_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_set_selection(&ctx, + data->selflag, data->selx, data->sely, + data->cx + data->ox, data->size + data->cy - data->oy); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_insert_lines(&ctx, ny); + for (i = 1; i < ny + 1; i++) + screen_draw_line(&ctx, i); + window_copy_draw_position(w, &ctx); + screen_draw_stop(&ctx); } diff --git a/window-more.c b/window-more.c index 1c0cc9bb..618b4f81 100644 --- a/window-more.c +++ b/window-more.c @@ -1,4 +1,4 @@ -/* $Id: window-more.c,v 1.4 2007-11-22 18:09:43 nicm Exp $ */ +/* $Id: window-more.c,v 1.5 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -24,7 +24,8 @@ void window_more_init(struct window *); void window_more_resize(struct window *, u_int, u_int); -void window_more_draw(struct window *, struct buffer *, u_int, u_int); +void window_more_draw( + struct window *, struct screen_draw_ctx *, u_int, u_int); void window_more_key(struct window *, int); void window_more_draw_position(struct window *, struct screen_draw_ctx *); @@ -90,8 +91,6 @@ window_more_draw_position(struct window *w, struct screen_draw_ctx *ctx) char *ptr, buf[32]; size_t len; char *line; - size_t n; - len = xsnprintf( buf, sizeof buf, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); @@ -102,68 +101,50 @@ window_more_draw_position(struct window *w, struct screen_draw_ctx *ctx) len -= len - screen_size_x(ctx->s); } - screen_draw_move(ctx, 0, 0); + screen_draw_move_cursor(ctx, 0, 0); if (data->top < ARRAY_LENGTH(&data->list)) { - line = ARRAY_ITEM(&data->list, data->top); - n = strlen(line); - if (n > screen_size_x(ctx->s) - len) - n = screen_size_x(ctx->s) - len; - buffer_write(ctx->b, line, n); - } else - n = 0; - for (; n < screen_size_x(ctx->s) - len; n++) - input_store8(ctx->b, SCREEN_DEFDATA); + line = xstrdup(ARRAY_ITEM(&data->list, data->top)); + if (strlen(line) > screen_size_x(ctx->s) - len) + line[screen_size_x(ctx->s) - len] = '\0'; + screen_draw_write_string(ctx, "%s", line); + xfree(line); + } + screen_draw_clear_line_to(ctx, screen_size_x(ctx->s) - len - 1); - screen_draw_move(ctx, screen_size_x(ctx->s) - len, 0); + screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); screen_draw_set_attributes(ctx, 0, status_colour); - buffer_write(ctx->b, buf, len); + screen_draw_write_string(ctx, "%s", ptr); } void window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py) { struct window_more_mode_data *data = w->modedata; - char *line; - size_t n; u_int p; - screen_draw_move(ctx, 0, py); + screen_draw_move_cursor(ctx, 0, py); screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); p = data->top + py; - if (p >= ARRAY_LENGTH(&data->list)) { - input_store_zero(ctx->b, CODE_CLEARLINE); - return; - } + if (p < ARRAY_LENGTH(&data->list)) + screen_draw_write_string(ctx, "%s", ARRAY_ITEM(&data->list, p)); - line = ARRAY_ITEM(&data->list, p); - n = strlen(line); - if (n > screen_size_x(ctx->s)) - n = screen_size_x(ctx->s); - buffer_write(ctx->b, line, n); - for (; n < screen_size_x(ctx->s); n++) - input_store8(ctx->b, SCREEN_DEFDATA); + screen_draw_clear_line_to(ctx, screen_last_x(ctx->s)); } void -window_more_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +window_more_draw( + struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) { - struct screen *s = &w->screen; - struct screen_draw_ctx ctx; - u_int i; - - screen_draw_start(&ctx, s, b, 0, 0); + u_int i; for (i = py; i < py + ny; i++) { if (i == 0) - continue; - window_more_draw_line(w, &ctx, i); + window_more_draw_position(w, ctx); + else + window_more_draw_line(w, ctx, i); } - if (py == 0) - window_more_draw_position(w, &ctx); - - screen_draw_stop(&ctx); } void @@ -189,7 +170,7 @@ window_more_key(struct window *w, int key) w->screen.mode &= ~MODE_BACKGROUND; recalculate_sizes(); - server_redraw_window_all(w); + server_redraw_window(w); return; case 'k': case 'K': @@ -217,47 +198,25 @@ window_more_key(struct window *w, int key) break; } if (top != data->top) - server_redraw_window_all(w); + server_redraw_window(w); } void window_more_up_1(struct window *w) { struct window_more_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i; - struct hdr hdr; - size_t size; if (data->top == 0) return; data->top--; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, 0, 0); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_INSERTLINE, 1); - window_more_draw_position(w, &ctx); - window_more_draw_line(w, &ctx, 1); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, 0, 0); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_insert_lines(&ctx, 1); + window_more_draw_position(w, &ctx); + window_more_draw_line(w, &ctx, 1); + screen_draw_stop(&ctx); } void @@ -266,36 +225,15 @@ window_more_down_1(struct window *w) struct window_more_mode_data *data = w->modedata; struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i; - struct hdr hdr; - size_t size; if (data->top >= ARRAY_LENGTH(&data->list)) return; data->top++; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, 0, 0); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_DELETELINE, 1); - window_more_draw_line(w, &ctx, screen_last_y(s)); - window_more_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, 0, 0); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_delete_lines(&ctx, 1); + window_more_draw_line(w, &ctx, screen_last_y(s)); + window_more_draw_position(w, &ctx); + screen_draw_stop(&ctx); } diff --git a/window-scroll.c b/window-scroll.c index f36bba5e..07d0663b 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -1,4 +1,4 @@ -/* $Id: window-scroll.c,v 1.12 2007-11-22 18:09:43 nicm Exp $ */ +/* $Id: window-scroll.c,v 1.13 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -24,7 +24,8 @@ void window_scroll_init(struct window *); void window_scroll_resize(struct window *, u_int, u_int); -void window_scroll_draw(struct window *, struct buffer *, u_int, u_int); +void window_scroll_draw( + struct window *, struct screen_draw_ctx *, u_int, u_int); void window_scroll_key(struct window *, int); void window_scroll_draw_position(struct window *, struct screen_draw_ctx *); @@ -83,33 +84,29 @@ window_scroll_draw_position(struct window *w, struct screen_draw_ctx *ctx) screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len); - screen_draw_move(ctx, screen_size_x(ctx->s) - len, 0); + screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); screen_draw_set_attributes(ctx, 0, status_colour); - buffer_write(ctx->b, ptr, len); } void -window_scroll_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +window_scroll_draw( + struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) { struct window_scroll_mode_data *data = w->modedata; struct screen *s = &w->screen; - struct screen_draw_ctx ctx; if (s->hsize != data->size) { data->oy += s->hsize - data->size; data->size = s->hsize; } - screen_draw_start(&ctx, s, b, data->ox, data->oy); if (py != 0) - screen_draw_lines(&ctx, py, ny); - else if (ny > 1) - screen_draw_lines(&ctx, py + 1, ny - 1); - - if (py == 0) - window_scroll_draw_position(w, &ctx); - - screen_draw_stop(&ctx); + screen_draw_lines(ctx, py, ny); + else { + if (ny > 1) + screen_draw_lines(ctx, py + 1, ny - 1); + window_scroll_draw_position(w, ctx); + } } void @@ -133,7 +130,7 @@ window_scroll_key(struct window *w, int key) w->screen.mode &= ~MODE_BACKGROUND; recalculate_sizes(); - server_redraw_window_all(w); + server_redraw_window(w); return; case 'h': case KEYC_LEFT: @@ -169,169 +166,84 @@ window_scroll_key(struct window *w, int key) break; } if (ox != data->ox || oy != data->oy) - server_redraw_window_all(w); + server_redraw_window(w); } void window_scroll_up_1(struct window *w) { struct window_scroll_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i; - struct hdr hdr; - size_t size; if (data->oy >= data->size) return; data->oy++; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_INSERTLINE, 1); - window_scroll_draw_position(w, &ctx); - screen_draw_line(&ctx, 1); /* nuke old position display */ - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_insert_lines(&ctx, 1); + window_scroll_draw_position(w, &ctx); + screen_draw_line(&ctx, 1); + screen_draw_stop(&ctx); } void window_scroll_down_1(struct window *w) { struct window_scroll_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i; - struct hdr hdr; - size_t size; if (data->oy == 0) return; data->oy--; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - screen_draw_move(&ctx, 0, 0); - input_store_one(c->out, CODE_DELETELINE, 1); - screen_draw_line(&ctx, screen_last_y(s)); - window_scroll_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + screen_draw_move_cursor(&ctx, 0, 0); + screen_draw_delete_lines(&ctx, 1); + screen_draw_line(&ctx, screen_last_y(&w->screen)); + window_scroll_draw_position(w, &ctx); + screen_draw_stop(&ctx); } void window_scroll_right_1(struct window *w) { struct window_scroll_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i, j; - struct hdr hdr; - size_t size; + u_int i; if (data->ox >= SHRT_MAX) return; data->ox++; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - for (j = 1; j < screen_size_y(s); j++) { - screen_draw_move(&ctx, 0, j); - input_store_one(c->out, CODE_DELETECHARACTER, 1); - } - screen_draw_column(&ctx, screen_last_x(s)); - window_scroll_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + for (i = 1; i < screen_size_y(&w->screen); i++) { + screen_draw_move_cursor(&ctx, 0, i); + screen_draw_delete_characters(&ctx, 1); + } + screen_draw_column(&ctx, screen_last_x(&w->screen)); + window_scroll_draw_position(w, &ctx); + screen_draw_stop(&ctx); } void window_scroll_left_1(struct window *w) { struct window_scroll_mode_data *data = w->modedata; - struct screen *s = &w->screen; struct screen_draw_ctx ctx; - struct client *c; - u_int i, j; - struct hdr hdr; - size_t size; + u_int i; if (data->ox == 0) return; data->ox--; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (!session_has(c->session, w)) - continue; - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw_start(&ctx, s, c->out, data->ox, data->oy); - for (j = 1; j < screen_size_y(s); j++) { - screen_draw_move(&ctx, 0, j); - input_store_one(c->out, CODE_INSERTCHARACTER, 1); - } - screen_draw_column(&ctx, 0); - window_scroll_draw_position(w, &ctx); - screen_draw_stop(&ctx); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } + screen_draw_start_window(&ctx, w, data->ox, data->oy); + for (i = 1; i < screen_size_y(&w->screen); i++) { + screen_draw_move_cursor(&ctx, 0, i); + screen_draw_insert_characters(&ctx, 1); + } + screen_draw_column(&ctx, 0); + window_scroll_draw_position(w, &ctx); + screen_draw_stop(&ctx); } diff --git a/window.c b/window.c index bb2611a2..a0dfdaf3 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.31 2007-11-21 19:53:57 nicm Exp $ */ +/* $Id: window.c,v 1.32 2007-11-27 19:23:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -274,24 +274,18 @@ window_resize(struct window *w, u_int sx, u_int sy) } void -window_parse(struct window *w, struct buffer *b) +window_parse(struct window *w) { - input_parse(w, b); + input_parse(w); } void -window_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +window_draw(struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) { - struct screen *s = &w->screen; - struct screen_draw_ctx ctx; - if (w->mode != NULL) - w->mode->draw(w, b, py, ny); - else { - screen_draw_start(&ctx, s, b, 0, 0); - screen_draw_lines(&ctx, py, ny); - screen_draw_stop(&ctx); - } + w->mode->draw(w, ctx, py, ny); + else + screen_draw_lines(ctx, py, ny); } void @@ -300,5 +294,5 @@ window_key(struct window *w, int key) if (w->mode != NULL) w->mode->key(w, key); else - input_key(w->out, key); + input_key(w, key); }