Big internal reorganisation to move tty control into parent.

This commit is contained in:
Nicholas Marriott 2007-11-27 19:23:34 +00:00
parent 97eca99d0b
commit 76c8a590db
30 changed files with 1577 additions and 1922 deletions

12
CHANGES
View File

@ -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 26 November 2007
* Rather than shifting up one line at a time once the history is full, * 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 (including mutt, emacs). No status bar yet and no key remapping or other
customisation. 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 $

View File

@ -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 .SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html .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 \ 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 \ 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 \ 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-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 \ 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-link-window.c cmd-unlink-window.c cmd-next-window.c \
cmd-swap-window.c cmd-rename-session.c cmd-kill-session.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-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 CC?= cc
INCDIRS+= -I. -I- -I/usr/local/include INCDIRS+= -I. -I- -I/usr/local/include

17
TODO
View File

@ -1,31 +1,16 @@
- it would be nice if there wasn't so much copying buffers about, audit uses
- useful env vars like WINDOW? - useful env vars like WINDOW?
- sort out who controls the buffers in local.c a bit
- better checking/emulation for missing term requirements - better checking/emulation for missing term requirements
- alt charset, borders etc (terminfo(5)/Line Graphics) - alt charset, borders etc (terminfo(5)/Line Graphics)
- new window command prompt - new window command prompt
- mouse handling and some other bits elinks needs - 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? - 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 - handle ioctl/termios stuff on window sockets
- figure out once and for all what is going on with backspace and del - figure out once and for all what is going on with backspace and del
backspace should be translated per the termios setting. backspace should be translated per the termios setting.
del passed through? del passed through?
- window creation/idle time - window creation/idle time
- attributes could be 8 not 16 bits
- profile/optimise, particularly (i suspect) input.c - profile/optimise, particularly (i suspect) input.c
- tidy up input.c a bit
- decide about customised status line - 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) - could use bsearch all over the place or get rid of smaller tables (clientmsg)
- better errors when creating new windows/sessions (how?) - better errors when creating new windows/sessions (how?)
- commands should have to care less about CMD_KEY - commands should have to care less about CMD_KEY
@ -71,6 +56,8 @@
in $x time (need window creation/use times) in $x time (need window creation/use times)
- lift SHRT_MAX limits for history - lift SHRT_MAX limits for history
- audit copy/scroll and other modes for problems with very small windows - 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 -------------------------------------------------------------------- -- For 0.2 --------------------------------------------------------------------
- window splitting? - window splitting?

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -53,3 +53,24 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
} }
return (0); 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;
}
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -179,3 +179,44 @@ buffer_read(struct buffer *b, void *data, size_t size)
memcpy(data, BUFFER_OUT(b), size); memcpy(data, BUFFER_OUT(b), size);
buffer_remove(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);
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -25,7 +25,6 @@
#include "tmux.h" #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_detach(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_error(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 **); 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 **); int (*fn)(struct hdr *, struct client_ctx *, char **);
}; };
struct client_msg client_msg_table[] = { struct client_msg client_msg_table[] = {
{ MSG_DATA, client_msg_fn_data },
{ MSG_DETACH, client_msg_fn_detach }, { MSG_DETACH, client_msg_fn_detach },
{ MSG_ERROR, client_msg_fn_error }, { MSG_ERROR, client_msg_fn_error },
{ MSG_EXIT, client_msg_fn_exit }, { MSG_EXIT, client_msg_fn_exit },
{ MSG_PAUSE, client_msg_fn_pause },
}; };
#define NCLIENTMSG (sizeof client_msg_table / sizeof client_msg_table[0]) #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"); 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 int
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error) client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
{ {

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,7 +33,6 @@
#include "tmux.h" #include "tmux.h"
void client_handle_winch(struct client_ctx *); void client_handle_winch(struct client_ctx *);
int client_process_local(struct client_ctx *, char **);
int int
client_init(const char *path, struct client_ctx *cctx, int start_server) 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) if (ttyname_r(STDIN_FILENO, data.tty, sizeof data.tty) != 0)
fatal("ttyname_r failed"); fatal("ttyname_r failed");
client_write_server(cctx, MSG_IDENTIFY, &data, sizeof data); client_write_server(cctx, MSG_IDENTIFY, &data, sizeof data);
cmd_send_string(cctx->srv_out, getenv("TERM"));
} }
return (0); return (0);
@ -121,13 +121,11 @@ retry:
int int
client_main(struct client_ctx *cctx) client_main(struct client_ctx *cctx)
{ {
struct pollfd pfds[2]; struct pollfd pfd;
char *error; char *error;
int timeout; int timeout;
siginit(); siginit();
if ((cctx->loc_fd = local_init(&cctx->loc_in, &cctx->loc_out)) == -1)
return (1);
logfile("client"); logfile("client");
#ifndef NO_SETPROCTITLE #ifndef NO_SETPROCTITLE
@ -140,34 +138,20 @@ client_main(struct client_ctx *cctx)
if (sigwinch) if (sigwinch)
client_handle_winch(cctx); client_handle_winch(cctx);
pfds[0].fd = cctx->srv_fd; pfd.fd = cctx->srv_fd;
pfds[0].events = POLLIN; pfd.events = POLLIN;
if (BUFFER_USED(cctx->srv_out) > 0) if (BUFFER_USED(cctx->srv_out) > 0)
pfds[0].events |= POLLOUT; pfd.events |= POLLOUT;
pfds[1].fd = cctx->loc_fd;
pfds[1].events = POLLIN;
if (BUFFER_USED(cctx->loc_out) > 0)
pfds[1].events |= POLLOUT;
if (poll(pfds, 2, timeout) == -1) { if (poll(&pfd, 1, timeout) == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
fatal("poll failed"); 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; 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)) { switch (client_msg_dispatch(cctx, &error)) {
case -1: case -1:
goto out; goto out;
@ -183,8 +167,6 @@ client_main(struct client_ctx *cctx)
} }
out: out:
local_done();
if (sigterm) { if (sigterm) {
printf("[terminated]\n"); printf("[terminated]\n");
return (1); return (1);
@ -204,14 +186,8 @@ out:
return (1); return (1);
server_dead: server_dead:
local_done();
printf("[lost server]\n"); printf("[lost server]\n");
return (0); return (0);
local_dead:
/* Can't do much here. Log and die. */
fatalx("local socket dead");
} }
void void
@ -229,24 +205,3 @@ client_handle_winch(struct client_ctx *cctx)
sigwinch = 0; 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);
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -83,6 +83,7 @@ void
cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx) cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx)
{ {
struct cmd_attach_session_data *data = ptr; struct cmd_attach_session_data *data = ptr;
char *cause;
if (ctx->flags & CMD_KEY) if (ctx->flags & CMD_KEY)
return; return;
@ -92,6 +93,12 @@ cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx)
return; return;
} }
if (tty_open(&ctx->cmdclient->tty, &cause) != 0) {
ctx->error(ctx, "%s", cause);
xfree(cause);
return;
}
if (data->flag_detach) if (data->flag_detach)
server_write_session(ctx->session, MSG_DETACH, NULL, 0); server_write_session(ctx->session, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = ctx->session; ctx->cmdclient->session = ctx->session;

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -47,7 +47,7 @@ cmd_copy_mode_exec(unused void *ptr, struct cmd_ctx *ctx)
if (w->mode == NULL && ctx->flags & CMD_KEY) { if (w->mode == NULL && ctx->flags & CMD_KEY) {
w->mode = &window_copy_mode; w->mode = &window_copy_mode;
w->mode->init(w); w->mode->init(w);
server_redraw_window_all(w); server_redraw_window(w);
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -51,8 +51,8 @@ cmd_list_clients_exec(unused void *ptr, struct cmd_ctx *ctx)
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
ctx->print(ctx, ctx->print(ctx, "%s: %s [%ux%u]",
"%s: %s [%ux%u]", c->tty, c->session->name, c->sx, c->sy); c->tty.path, c->session->name, c->sx, c->sy);
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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 *data = ptr;
struct cmd_new_session_data std = { NULL, NULL, NULL, 0 }; struct cmd_new_session_data std = { NULL, NULL, NULL, 0 };
struct client *c; struct client *c = ctx->cmdclient;
char *cmd; char *cmd, *cause;
u_int sy; u_int sy;
if (data == NULL) if (data == NULL)
@ -110,7 +110,6 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
if (ctx->flags & CMD_KEY) if (ctx->flags & CMD_KEY)
return; return;
c = ctx->cmdclient;
if (!data->flag_detached && !(c->flags & CLIENT_TERMINAL)) { if (!data->flag_detached && !(c->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal"); ctx->error(ctx, "not a terminal");
return; return;
@ -126,6 +125,12 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
sy = status_lines + 1; sy = status_lines + 1;
sy -= status_lines; sy -= status_lines;
if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) {
ctx->error(ctx, "%s", cause);
xfree(cause);
return;
}
cmd = data->cmd; cmd = data->cmd;
if (cmd == NULL) if (cmd == NULL)
cmd = default_command; cmd = default_command;

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -47,7 +47,7 @@ cmd_scroll_mode_exec(unused void *ptr, struct cmd_ctx *ctx)
if (w->mode == NULL && ctx->flags & CMD_KEY) { if (w->mode == NULL && ctx->flags & CMD_KEY) {
w->mode = &window_scroll_mode; w->mode = &window_scroll_mode;
w->mode->init(w); w->mode->init(w);
server_redraw_window_all(w); server_redraw_window(w);
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -55,13 +55,13 @@ struct {
/* Translate a key code from client into an output key sequence. */ /* Translate a key code from client into an output key sequence. */
void void
input_key(struct buffer *b, int key) input_key(struct window *w, int key)
{ {
u_int i; u_int i;
log_debug2("writing key %d", key); log_debug2("writing key %d", key);
if (key != KEYC_NONE && key >= 0) { if (key != KEYC_NONE && key >= 0) {
input_store8(b, key); buffer_write8(w->out, (uint8_t) key);
return; return;
} }
@ -69,8 +69,8 @@ input_key(struct buffer *b, int key)
if (input_keys[i].key == key) { if (input_keys[i].key == key) {
log_debug2( log_debug2(
"found key %d: \"%s\"", key, input_keys[i].data); "found key %d: \"%s\"", key, input_keys[i].data);
buffer_write( buffer_write(w->out,
b, input_keys[i].data, strlen(input_keys[i].data)); input_keys[i].data, strlen(input_keys[i].data));
return; return;
} }
} }

217
input.c
View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -36,7 +36,9 @@
int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t); int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t);
int input_new_argument(struct input_ctx *); 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_first(u_char, struct input_ctx *);
void *input_state_escape(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); 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 void
input_init(struct window *w) input_init(struct window *w)
{ {
@ -146,7 +161,7 @@ input_free(struct window *w)
} }
void void
input_parse(struct window *w, struct buffer *b) input_parse(struct window *w)
{ {
struct input_ctx *ictx = &w->ictx; struct input_ctx *ictx = &w->ictx;
u_char ch; u_char ch;
@ -159,7 +174,6 @@ input_parse(struct window *w, struct buffer *b)
ictx->off = 0; ictx->off = 0;
ictx->w = w; ictx->w = w;
ictx->b = b;
log_debug2("entry; buffer=%zu", ictx->len); 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) { switch (ictx->title_type) {
case 0: case 0:
strlcpy(s->title, ictx->title_buf, sizeof s->title); strlcpy(s->title, ictx->title_buf, sizeof s->title);
input_store_one(ictx->b, CODE_TITLE, ictx->title_len); input_write(ictx, TTY_TITLE, s->title);
buffer_write(ictx->b, ictx->title_buf, ictx->title_len);
break; break;
} }
return (input_state_first); 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); log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
if (s->cx == screen_size_x(s)) { if (s->cx == screen_size_x(s)) {
if (!screen_hidden(s)) { input_write(ictx, TTY_CHARACTER, '\r');
input_store8(ictx->b, '\r'); input_write(ictx, TTY_CHARACTER, '\n');
input_store8(ictx->b, '\n');
}
s->cx = 0; s->cx = 0;
screen_display_cursor_down(s); screen_display_cursor_down(s);
@ -384,8 +395,7 @@ input_handle_character(u_char ch, struct input_ctx *ictx)
return; return;
screen_display_cursor_set(s, ch); screen_display_cursor_set(s, ch);
if (!screen_hidden(s)) input_write(ictx, TTY_CHARACTER, ch);
input_store8(ictx->b, ch);
s->cx++; s->cx++;
} }
@ -399,7 +409,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx)
switch (ch) { switch (ch) {
case '\0': /* NUL */ case '\0': /* NUL */
break; return;
case '\n': /* LF */ case '\n': /* LF */
screen_display_cursor_down(s); screen_display_cursor_down(s);
break; break;
@ -419,28 +429,21 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx)
s->cx = 0; s->cx = 0;
screen_display_cursor_down(s); screen_display_cursor_down(s);
} }
if (screen_hidden(s)) input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
return;
input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1);
return; return;
case '\016': /* SO */ case '\016': /* SO */
s->attr |= ATTR_DRAWING; s->attr |= ATTR_DRAWING;
if (screen_hidden(s)) input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr);
return;
input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr);
return; return;
case '\017': /* SI */ case '\017': /* SI */
s->attr &= ~ATTR_DRAWING; s->attr &= ~ATTR_DRAWING;
if (screen_hidden(s)) input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr);
return;
input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr);
return; return;
default: default:
log_debug("unknown c0: %hhu", ch); log_debug("unknown c0: %hhu", ch);
return; return;
} }
if (!screen_hidden(s)) input_write(ictx, TTY_CHARACTER, ch);
input_store8(ictx->b, ch);
} }
void void
@ -453,8 +456,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx)
switch (ch) { switch (ch) {
case 'M': /* RI */ case 'M': /* RI */
screen_display_cursor_up(s); screen_display_cursor_up(s);
if (!screen_hidden(s)) input_write(ictx, TTY_REVERSEINDEX);
input_store_zero(ictx->b, CODE_REVERSEINDEX);
break; break;
default: default:
log_debug("unknown c1: %hhu", ch); log_debug("unknown c1: %hhu", ch);
@ -471,12 +473,10 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx)
switch (ch) { switch (ch) {
case '=': /* DECKPAM */ case '=': /* DECKPAM */
if (!screen_hidden(s)) input_write(ictx, TTY_KKEYPADON);
input_store_zero(ictx->b, CODE_KKEYPADON);
break; break;
case '>': /* DECKPNM*/ case '>': /* DECKPNM*/
if (!screen_hidden(s)) input_write(ictx, TTY_KKEYPADOFF);
input_store_zero(ictx->b, CODE_KKEYPADOFF);
break; break;
case '7': /* DECSC */ case '7': /* DECSC */
s->saved_cx = s->cx; 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->cy = s->saved_cy;
s->attr = s->saved_attr; s->attr = s->saved_attr;
s->colr = s->saved_colr; s->colr = s->saved_colr;
if (screen_hidden(s)) input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr);
break; input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr);
input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1);
break; break;
default: default:
log_debug("unknown p2: %hhu", ch); log_debug("unknown p2: %hhu", ch);
@ -583,8 +581,7 @@ input_handle_sequence_cuu(struct input_ctx *ictx)
} }
s->cy -= n; s->cy -= n;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORUP, n);
input_store_one(ictx->b, CODE_CURSORUP, n);
} }
void void
@ -606,8 +603,7 @@ input_handle_sequence_cud(struct input_ctx *ictx)
input_limit(n, 1, screen_last_y(s) - s->cy); input_limit(n, 1, screen_last_y(s) - s->cy);
s->cy += n; s->cy += n;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORDOWN, n);
input_store_one(ictx->b, CODE_CURSORDOWN, n);
} }
void void
@ -629,8 +625,7 @@ input_handle_sequence_cuf(struct input_ctx *ictx)
input_limit(n, 1, screen_last_x(s) - s->cx); input_limit(n, 1, screen_last_x(s) - s->cx);
s->cx += n; s->cx += n;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORRIGHT, n);
input_store_one(ictx->b, CODE_CURSORRIGHT, n);
} }
void void
@ -653,8 +648,7 @@ input_handle_sequence_cub(struct input_ctx *ictx)
} }
s->cx -= n; s->cx -= n;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORLEFT, n);
input_store_one(ictx->b, CODE_CURSORLEFT, n);
} }
void void
@ -676,8 +670,7 @@ input_handle_sequence_dch(struct input_ctx *ictx)
input_limit(n, 1, screen_last_x(s) - s->cx); input_limit(n, 1, screen_last_x(s) - s->cx);
screen_display_delete_characters(s, s->cx, s->cy, n); screen_display_delete_characters(s, s->cx, s->cy, n);
if (!screen_hidden(s)) input_write(ictx, TTY_DELETECHARACTER, n);
input_store_one(ictx->b, CODE_DELETECHARACTER, n);
} }
void void
@ -702,8 +695,7 @@ input_handle_sequence_dl(struct input_ctx *ictx)
screen_display_delete_lines(s, s->cy, n); screen_display_delete_lines(s, s->cy, n);
else else
screen_display_delete_lines_region(s, s->cy, n); screen_display_delete_lines_region(s, s->cy, n);
if (!screen_hidden(s)) input_write(ictx, TTY_DELETELINE, n);
input_store_one(ictx->b, CODE_DELETELINE, n);
} }
void void
@ -725,8 +717,7 @@ input_handle_sequence_ich(struct input_ctx *ictx)
input_limit(n, 1, screen_last_x(s) - s->cx); input_limit(n, 1, screen_last_x(s) - s->cx);
screen_display_insert_characters(s, s->cx, s->cy, n); screen_display_insert_characters(s, s->cx, s->cy, n);
if (!screen_hidden(s)) input_write(ictx, TTY_INSERTCHARACTER, n);
input_store_one(ictx->b, CODE_INSERTCHARACTER, n);
} }
void void
@ -751,8 +742,7 @@ input_handle_sequence_il(struct input_ctx *ictx)
screen_display_insert_lines(s, s->cy, n); screen_display_insert_lines(s, s->cy, n);
else else
screen_display_insert_lines_region(s, s->cy, n); screen_display_insert_lines_region(s, s->cy, n);
if (!screen_hidden(s)) input_write(ictx, TTY_INSERTLINE, n);
input_store_one(ictx->b, CODE_INSERTLINE, n);
} }
void void
@ -774,8 +764,7 @@ input_handle_sequence_vpa(struct input_ctx *ictx)
input_limit(n, 1, screen_size_y(s)); input_limit(n, 1, screen_size_y(s));
s->cy = n - 1; s->cy = n - 1;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
input_store_two(ictx->b, CODE_CURSORMOVE, n, s->cx + 1);
} }
void void
@ -797,8 +786,7 @@ input_handle_sequence_hpa(struct input_ctx *ictx)
input_limit(n, 1, screen_size_x(s)); input_limit(n, 1, screen_size_x(s));
s->cx = n - 1; s->cx = n - 1;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, n);
} }
void void
@ -822,8 +810,7 @@ input_handle_sequence_cup(struct input_ctx *ictx)
s->cx = m - 1; s->cx = m - 1;
s->cy = n - 1; s->cy = n - 1;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
input_store_two(ictx->b, CODE_CURSORMOVE, n, m);
} }
void void
@ -849,28 +836,21 @@ input_handle_sequence_ed(struct input_ctx *ictx)
screen_display_fill_cursor_eos( screen_display_fill_cursor_eos(
s, SCREEN_DEFDATA, s->attr, s->colr); s, SCREEN_DEFDATA, s->attr, s->colr);
if (screen_hidden(s)) for (i = s->cy; i < screen_size_y(s); i++) {
break; input_write(ictx, TTY_CURSORMOVE, i, 0);
input_store_zero(ictx->b, CODE_CLEARLINE); input_write(ictx, TTY_CLEARENDOFLINE);
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);
} }
input_store_two( input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1);
break; break;
case 2: case 2:
screen_display_fill_lines( screen_display_fill_lines(
s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr); 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++) { for (i = 0; i < screen_size_y(s); i++) {
input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); input_write(ictx, TTY_CURSORMOVE, i, 0);
input_store_zero(ictx->b, CODE_CLEARLINE); input_write(ictx, TTY_CLEARENDOFLINE);
} }
input_store_two( input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1);
break; break;
} }
} }
@ -896,23 +876,17 @@ input_handle_sequence_el(struct input_ctx *ictx)
case 0: case 0:
screen_display_fill_cursor_eol( screen_display_fill_cursor_eol(
s, SCREEN_DEFDATA, s->attr, s->colr); s, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARENDOFLINE);
if (!screen_hidden(s))
input_store_zero(ictx->b, CODE_CLEARENDOFLINE);
break; break;
case 1: case 1:
screen_display_fill_cursor_bol( screen_display_fill_cursor_bol(
s, SCREEN_DEFDATA, s->attr, s->colr); s, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARSTARTOFLINE);
if (!screen_hidden(s))
input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE);
break; break;
case 2: case 2:
screen_display_fill_line( screen_display_fill_line(
s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); s, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARLINE);
if (!screen_hidden(s))
input_store_zero(ictx->b, CODE_CLEARLINE);
break; break;
} }
} }
@ -932,13 +906,11 @@ input_handle_sequence_sm(struct input_ctx *ictx)
switch (n) { switch (n) {
case 1: /* GATM */ case 1: /* GATM */
s->mode |= MODE_KCURSOR; s->mode |= MODE_KCURSOR;
if (!screen_hidden(s)) input_write(ictx, TTY_KCURSORON);
input_store_zero(ictx->b, CODE_KCURSORON);
break; break;
case 25: /* TCEM */ case 25: /* TCEM */
s->mode |= MODE_CURSOR; s->mode |= MODE_CURSOR;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSORON);
input_store_zero(ictx->b, CODE_CURSORON);
break; break;
default: default:
log_debug("unknown SM [%hhu]: %u", ictx->private, n); log_debug("unknown SM [%hhu]: %u", ictx->private, n);
@ -948,8 +920,7 @@ input_handle_sequence_sm(struct input_ctx *ictx)
switch (n) { switch (n) {
case 4: /* IRM */ case 4: /* IRM */
s->mode |= MODE_INSERT; s->mode |= MODE_INSERT;
if (!screen_hidden(s)) input_write(ictx, TTY_INSERTON);
input_store_zero(ictx->b, CODE_INSERTON);
break; break;
case 34: case 34:
/* Cursor high visibility not supported. */ /* Cursor high visibility not supported. */
@ -976,13 +947,11 @@ input_handle_sequence_rm(struct input_ctx *ictx)
switch (n) { switch (n) {
case 1: /* GATM */ case 1: /* GATM */
s->mode &= ~MODE_KCURSOR; s->mode &= ~MODE_KCURSOR;
if (!screen_hidden(s)) input_write(ictx, TTY_KCURSOROFF);
input_store_zero(ictx->b, CODE_KCURSOROFF);
break; break;
case 25: /* TCEM */ case 25: /* TCEM */
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
if (!screen_hidden(s)) input_write(ictx, TTY_CURSOROFF);
input_store_zero(ictx->b, CODE_CURSOROFF);
break; break;
default: default:
log_debug("unknown RM [%hhu]: %u", ictx->private, n); log_debug("unknown RM [%hhu]: %u", ictx->private, n);
@ -992,8 +961,7 @@ input_handle_sequence_rm(struct input_ctx *ictx)
switch (n) { switch (n) {
case 4: /* IRM */ case 4: /* IRM */
s->mode &= ~MODE_INSERT; s->mode &= ~MODE_INSERT;
if (!screen_hidden(s)) input_write(ictx, TTY_INSERTOFF);
input_store_zero(ictx->b, CODE_INSERTOFF);
break; break;
case 34: case 34:
/* Cursor high visibility not supported. */ /* Cursor high visibility not supported. */
@ -1067,8 +1035,7 @@ input_handle_sequence_decstbm(struct input_ctx *ictx)
s->rupper = n - 1; s->rupper = n - 1;
s->rlower = m - 1; s->rlower = m - 1;
if (!screen_hidden(s)) input_write(ictx, TTY_SCROLLREGION, s->rupper, s->rlower);
input_store_two(ictx->b, CODE_SCROLLREGION, n, m);
} }
void void
@ -1152,67 +1119,5 @@ input_handle_sequence_sgr(struct input_ctx *ictx)
} }
} }
} }
if (!screen_hidden(s)) input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr);
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);
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -204,5 +204,5 @@ key_bindings_dispatch(int key, struct client *c)
cmd_exec(bd->cmd, &ctx); cmd_exec(bd->cmd, &ctx);
if (c->session->curw->window->mode == &window_more_mode) if (c->session->curw->window->mode == &window_more_mode)
server_redraw_window_all(c->session->curw->window); server_redraw_window(c->session->curw->window);
} }

793
local.c
View File

@ -1,793 +0,0 @@
/* $Id: local.c,v 1.23 2007-11-26 20:36:30 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <curses.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define TTYDEFCHARS
/* glibc requires unistd.h before termios.h for TTYDEFCHARS. */
#include <unistd.h>
#include <termios.h>
#include <term.h>
#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);
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -117,8 +117,8 @@ recalculate_sizes(void)
log_debug("window size %u,%u (was %u,%u)", ssx, ssy, log_debug("window size %u,%u (was %u,%u)", ssx, ssy,
screen_size_x(&w->screen), screen_size_y(&w->screen)); screen_size_x(&w->screen), screen_size_y(&w->screen));
server_clear_window_cur(w);
window_resize(w, ssx, ssy); window_resize(w, ssx, ssy);
server_redraw_window_cur(w); server_clear_window(w);
server_redraw_window(w);
} }
} }

155
screen.c
View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -267,13 +267,45 @@ screen_destroy(struct screen *s)
xfree(s->grid_size); 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. */ /* Initialise drawing. */
void void
screen_draw_start(struct screen_draw_ctx *ctx, screen_draw_start(struct screen_draw_ctx *ctx, struct screen *s,
struct screen *s, struct buffer *b, u_int ox, u_int oy) void (*write)(void *, int, ...), void *data, u_int ox, u_int oy)
{ {
ctx->write = write;
ctx->data = data;
ctx->s = s; ctx->s = s;
ctx->b = b;
ctx->ox = ox; ctx->ox = ox;
ctx->oy = oy; ctx->oy = oy;
@ -287,8 +319,8 @@ screen_draw_start(struct screen_draw_ctx *ctx,
ctx->attr = s->attr; ctx->attr = s->attr;
ctx->colr = s->colr; ctx->colr = s->colr;
input_store_two(b, CODE_SCROLLREGION, 1, screen_size_y(s)); ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s));
input_store_zero(b, CODE_CURSOROFF); ctx->write(ctx->data, TTY_CURSOROFF);
} }
/* Set selection. */ /* Set selection. */
@ -356,44 +388,112 @@ void
screen_draw_stop(struct screen_draw_ctx *ctx) screen_draw_stop(struct screen_draw_ctx *ctx)
{ {
struct screen *s = ctx->s; 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) 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) 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_BACKGROUND) {
if (s->mode & MODE_BGCURSOR) if (s->mode & MODE_BGCURSOR)
input_store_zero(b, CODE_CURSORON); ctx->write(ctx->data, TTY_CURSORON);
} else { } else {
if (s->mode & MODE_CURSOR) 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. */ /* Move cursor. */
void 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) if (px == ctx->cx && py == ctx->cy)
return; return;
/* XXX disabled while things outside can move the cursor (eg
window-more.c writes characters)
if (px == 0 && py == ctx->cy) 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) 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) { else if (px == 0 && py == ctx->cy + 1) {
input_store8(ctx->b, '\r'); ctx->write(ctx->data, TTY_CHARACTER, '\r');
input_store8(ctx->b, '\n'); ctx->write(ctx->data, TTY_CHARACTER, '\n');
} else } else
*/ ctx->write(ctx->data, TTY_CURSORMOVE, py, px);
input_store_two(ctx->b, CODE_CURSORMOVE, py + 1, px + 1);
ctx->cx = px; ctx->cx = px;
ctx->cy = py; ctx->cy = py;
@ -405,7 +505,7 @@ screen_draw_set_attributes(
struct screen_draw_ctx *ctx, u_char attr, u_char colr) struct screen_draw_ctx *ctx, u_char attr, u_char colr)
{ {
if (attr != ctx->attr || colr != ctx->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->attr = attr;
ctx->colr = colr; ctx->colr = colr;
} }
@ -415,14 +515,13 @@ screen_draw_set_attributes(
void void
screen_draw_cell(struct screen_draw_ctx *ctx, u_int px, u_int py) 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_get_cell(ctx, px, py, &data, &attr, &colr);
screen_draw_set_attributes(ctx, 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 * 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)); screen_draw_cells(ctx, 0, py, screen_size_x(ctx->s));
else { else {
screen_draw_cells(ctx, 0, py, cx); screen_draw_cells(ctx, 0, py, cx);
screen_draw_move(ctx, cx, py); screen_draw_move_cursor(ctx, cx, py);
input_store_zero(ctx->b, CODE_CLEARENDOFLINE); ctx->write(ctx->data, TTY_CLEARENDOFLINE);
} }
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -105,7 +105,7 @@ server_write_session(
} }
void void
server_write_window_cur( server_write_window(
struct window *w, enum hdrtype type, const void *buf, size_t len) struct window *w, enum hdrtype type, const void *buf, size_t len)
{ {
struct client *c; 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 void
server_clear_client(struct client *c) server_clear_client(struct client *c)
{ {
struct screen *s = &c->session->curw->window->screen; struct screen_draw_ctx ctx;
struct hdr hdr;
size_t size;
u_int i;
buffer_ensure(c->out, sizeof hdr); screen_draw_start_client(&ctx, c, 0, 0);
buffer_add(c->out, sizeof hdr); screen_draw_clear_screen(&ctx);
size = BUFFER_USED(c->out); screen_draw_stop(&ctx);
input_store_zero(c->out, CODE_CURSOROFF); status_write_client(c);
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);
} }
void void
server_redraw_client(struct client *c) server_redraw_client(struct client *c)
{ {
struct window *w = c->session->curw->window; struct screen_draw_ctx ctx;
struct hdr hdr; struct window *w = c->session->curw->window;
size_t size;
buffer_ensure(c->out, sizeof hdr); screen_draw_start_client(&ctx, c, 0, 0);
buffer_add(c->out, sizeof hdr); window_draw(w, &ctx, 0, screen_size_y(&w->screen));
size = BUFFER_USED(c->out); 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; void
log_debug("redrawing window, %zu bytes", size); server_status_client(struct client *c)
if (size != 0) { {
hdr.type = MSG_DATA; status_write_client(c);
hdr.size = size; }
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
} else
buffer_reverse_add(c->out, sizeof hdr);
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 void
server_redraw_session(struct session *s) server_redraw_session(struct session *s)
{ {
struct client *c; struct screen_draw_ctx ctx;
u_int i; struct window *w = s->curw->window;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_session(&ctx, s, 0, 0);
c = ARRAY_ITEM(&clients, i); window_draw(w, &ctx, 0, screen_size_y(&w->screen));
if (c != NULL && c->session == s) screen_draw_stop(&ctx);
server_redraw_client(c);
} status_write_session(s);
} }
void void
server_status_session(struct session *s) server_status_session(struct session *s)
{ {
struct client *c; status_write_session(s);
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);
}
} }
void void
server_clear_window_cur(struct window *w) server_clear_window(struct window *w)
{ {
struct client *c; struct screen_draw_ctx ctx;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, 0, 0);
c = ARRAY_ITEM(&clients, i); screen_draw_clear_screen(&ctx);
if (c != NULL && screen_draw_stop(&ctx);
c->session != NULL && c->session->curw->window == w)
server_clear_client(c); status_write_window(w);
}
} }
void void
server_clear_window_all(struct window *w) server_redraw_window(struct window *w)
{ {
struct client *c; struct screen_draw_ctx ctx;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, 0, 0);
c = ARRAY_ITEM(&clients, i); window_draw(w, &ctx, 0, screen_size_y(&w->screen));
if (c == NULL || c->session == NULL) screen_draw_stop(&ctx);
continue;
if (session_has(c->session, w)) status_write_window(w);
server_redraw_client(c);
}
} }
void void
server_redraw_window_cur(struct window *w) server_status_window(struct window *w)
{ {
struct client *c; struct session *s;
u_int i; u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { /*
c = ARRAY_ITEM(&clients, i); * This is slightly different. We want to redraw the status line of any
if (c != NULL && * clients containing this window rather than any where it is the
c->session != NULL && c->session->curw->window == w) * current window.
server_redraw_client(c); */
}
}
void for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
server_redraw_window_all(struct window *w) s = ARRAY_ITEM(&sessions, i);
{ if (s != NULL && session_has(s, w))
struct client *c; server_status_session(s);
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);
} }
} }
void printflike2 void printflike2
server_write_message(struct client *c, const char *fmt, ...) server_write_message(struct client *c, const char *fmt, ...)
{ {
struct window *w = c->session->curw->window;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct hdr hdr;
va_list ap; va_list ap;
char *msg; char *msg;
size_t size; size_t size;
u_int i;
buffer_ensure(c->out, sizeof hdr); screen_draw_start_client(&ctx, c, 0, 0);
buffer_add(c->out, sizeof hdr); screen_draw_move_cursor(&ctx, 0, c->sy - 1);
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_set_attributes(&ctx, ATTR_REVERSE, 0x88); screen_draw_set_attributes(&ctx, ATTR_REVERSE, 0x88);
va_start(ap, fmt); va_start(ap, fmt);
xvasprintf(&msg, fmt, ap); xvasprintf(&msg, fmt, ap);
va_end(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'; msg[c->sx - 1] = '\0';
buffer_write(c->out, msg, strlen(msg)); memset(msg + size, SCREEN_DEFDATA, (c->sx - 1) - size);
for (i = strlen(msg); i < c->sx; i++) }
input_store8(c->out, ' '); screen_draw_write_string(&ctx, "%s", msg);
xfree(msg); xfree(msg);
size = BUFFER_USED(c->out) - size; buffer_flush(c->tty.fd, c->tty.in, c->tty.out);
hdr.type = MSG_DATA; usleep(750000);
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
hdr.type = MSG_PAUSE; if (status_lines == 0) {
hdr.size = 0; window_draw(c->session->curw->window, &ctx, c->sy - 1, 1);
buffer_write(c->out, &hdr, sizeof hdr); screen_draw_stop(&ctx);
} else {
buffer_ensure(c->out, sizeof hdr); screen_draw_stop(&ctx);
buffer_add(c->out, sizeof hdr); status_write_client(c);
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);
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -26,7 +28,6 @@
int server_msg_fn_command(struct hdr *, struct client *); int server_msg_fn_command(struct hdr *, struct client *);
int server_msg_fn_identify(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 *); int server_msg_fn_resize(struct hdr *, struct client *);
void printflike2 server_msg_fn_command_error( 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_IDENTIFY, server_msg_fn_identify },
{ MSG_COMMAND, server_msg_fn_command }, { MSG_COMMAND, server_msg_fn_command },
{ MSG_RESIZE, server_msg_fn_resize }, { MSG_RESIZE, server_msg_fn_resize },
{ MSG_KEYS, server_msg_fn_keys },
}; };
#define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0]) #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++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
/* XXX fnmatch, multi clients etc */ /* XXX fnmatch, multi clients etc */
c = ARRAY_ITEM(&clients, i); 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; ctx.client = c;
} }
if (ctx.client == NULL) { if (ctx.client == NULL) {
@ -192,10 +192,12 @@ int
server_msg_fn_identify(struct hdr *hdr, struct client *c) server_msg_fn_identify(struct hdr *hdr, struct client *c)
{ {
struct msg_identify_data data; struct msg_identify_data data;
char *term;
if (hdr->size < sizeof data) if (hdr->size < sizeof data)
fatalx("bad MSG_IDENTIFY size"); fatalx("bad MSG_IDENTIFY size");
buffer_read(c->in, &data, sizeof data); 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); 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; c->sy = data.sy;
data.tty[(sizeof data.tty) - 1] = '\0'; 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; c->flags |= CLIENT_TERMINAL;
@ -235,34 +238,3 @@ server_msg_fn_resize(struct hdr *hdr, struct client *c)
return (0); 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);
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -49,6 +49,7 @@ void server_handle_windows(struct pollfd **);
void server_fill_clients(struct pollfd **); void server_fill_clients(struct pollfd **);
void server_handle_clients(struct pollfd **); void server_handle_clients(struct pollfd **);
struct client *server_accept_client(int); struct client *server_accept_client(int);
void server_handle_client(struct client *);
void server_handle_window(struct window *); void server_handle_window(struct window *);
void server_lost_client(struct client *); void server_lost_client(struct client *);
void server_lost_window(struct window *); void server_lost_window(struct window *);
@ -139,7 +140,7 @@ server_main(const char *srv_path, int srv_fd)
pfds = NULL; pfds = NULL;
while (!sigterm) { while (!sigterm) {
/* Initialise pollfd array. */ /* 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); pfds = xrealloc(pfds, nfds, sizeof *pfds);
pfd = pfds; pfd = pfds;
@ -246,7 +247,9 @@ server_fill_clients(struct pollfd **pfd)
u_int i; u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); 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; (*pfd)->fd = -1;
else { else {
(*pfd)->fd = c->fd; (*pfd)->fd = c->fd;
@ -255,6 +258,16 @@ server_fill_clients(struct pollfd **pfd)
(*pfd)->events |= POLLOUT; (*pfd)->events |= POLLOUT;
} }
(*pfd)++; (*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; u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if ((c = ARRAY_ITEM(&clients, i)) != NULL) { c = ARRAY_ITEM(&clients, i);
if (buffer_poll(*pfd, c->in, c->out) != 0)
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); server_lost_client(c);
else else
server_msg_dispatch(c); server_handle_client(c);
} }
(*pfd)++; (*pfd)++;
} }
@ -302,6 +327,8 @@ server_accept_client(int srv_fd)
c->in = buffer_create(BUFSIZ); c->in = buffer_create(BUFSIZ);
c->out = buffer_create(BUFSIZ); c->out = buffer_create(BUFSIZ);
c->tty.fd = -1;
c->session = NULL; c->session = NULL;
c->sx = 80; c->sx = 80;
c->sy = 25; c->sy = 25;
@ -316,6 +343,25 @@ server_accept_client(int srv_fd)
return (c); 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. */ /* Lost a client. */
void void
server_lost_client(struct client *c) server_lost_client(struct client *c)
@ -327,8 +373,8 @@ server_lost_client(struct client *c)
ARRAY_SET(&clients, i, NULL); ARRAY_SET(&clients, i, NULL);
} }
if (c->tty != NULL) tty_free(&c->tty);
xfree(c->tty);
close(c->fd); close(c->fd);
buffer_destroy(c->in); buffer_destroy(c->in);
buffer_destroy(c->out); buffer_destroy(c->out);
@ -341,17 +387,10 @@ server_lost_client(struct client *c)
void void
server_handle_window(struct window *w) server_handle_window(struct window *w)
{ {
struct buffer *b;
struct session *s; struct session *s;
u_int i; u_int i;
b = buffer_create(BUFSIZ); window_parse(w);
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);
if (!(w->flags & WINDOW_BELL)) if (!(w->flags & WINDOW_BELL))
return; return;
@ -364,17 +403,17 @@ server_handle_window(struct window *w)
switch (bell_action) { switch (bell_action) {
case BELL_ANY: case BELL_ANY:
server_write_window_all(w, MSG_DATA, "\007", 1); tty_write_window(w, TTY_CHARACTER, '\007');
break; break;
case BELL_CURRENT: case BELL_CURRENT:
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i); s = ARRAY_ITEM(&sessions, i);
if (s != NULL && s->curw->window == w) if (s != NULL && s->curw->window == w)
server_write_session(s, MSG_DATA, "\007", 1); tty_write_session(s, TTY_CHARACTER, '\007');
} }
break; break;
} }
server_status_window_all(w); server_status_window(w);
w->flags &= ~WINDOW_BELL; w->flags &= ~WINDOW_BELL;
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -25,19 +25,19 @@
void printflike3 status_print(struct buffer *, size_t *, const char *, ...); void printflike3 status_print(struct buffer *, size_t *, const char *, ...);
void void
status_write(struct client *c) status_write_client(struct client *c)
{ {
struct screen *s = &c->session->curw->window->screen; struct screen_draw_ctx ctx;
struct buffer *b = c->out; struct winlink *wl;
struct winlink *wl; char flag;
size_t size;
char flag;
input_store_zero(b, CODE_CURSOROFF); if (status_lines == 0 || c->sy <= status_lines)
input_store_two(b, CODE_CURSORMOVE, c->sy - status_lines + 1, 1); return;
input_store_two(b, CODE_ATTRIBUTES, 0, status_colour);
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) { RB_FOREACH(wl, winlinks, &c->session->windows) {
flag = ' '; flag = ' ';
if (wl == c->session->lastw) if (wl == c->session->lastw)
@ -46,45 +46,50 @@ status_write(struct client *c)
flag = '*'; flag = '*';
if (session_hasbell(c->session, wl)) if (session_hasbell(c->session, wl))
flag = '!'; flag = '!';
status_print( screen_draw_write_string(
b, &size, "%d:%s%c ", wl->idx, wl->window->name, flag); &ctx, "%d:%s%c ", wl->idx, wl->window->name, flag);
if (size == 0) if (ctx.cx >= screen_last_x(ctx.s))
break; break;
} }
while (size-- > 0) screen_draw_clear_line_to(&ctx, screen_last_x(ctx.s));
input_store8(b, ' ');
input_store_two(b, CODE_ATTRIBUTES, s->attr, s->colr); screen_draw_stop(&ctx);
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);
}
} }
void printflike3 void
status_print(struct buffer *b, size_t *size, const char *fmt, ...) status_write_window(struct window *w)
{ {
va_list ap; struct client *c;
char *msg, *ptr; u_int i;
int n;
va_start(ap, fmt); if (w->screen.mode & MODE_HIDDEN)
n = xvasprintf(&msg, fmt, ap); return;
va_end(ap);
if ((size_t) n > *size) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
msg[*size] = '\0'; c = ARRAY_ITEM(&clients, i);
n = *size; 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);
} }

208
tmux.h
View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,6 +41,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <term.h>
#include "array.h" #include "array.h"
@ -255,34 +256,32 @@ struct buffer {
#define KEYC_UP -149 #define KEYC_UP -149
#define KEYC_MOUSE -150 #define KEYC_MOUSE -150
/* Translated escape codes. */ /* Output codes. */
#define CODE_CURSORUP 0 #define TTY_CHARACTER 0
#define CODE_CURSORDOWN 1 #define TTY_CURSORUP 1
#define CODE_CURSORRIGHT 2 #define TTY_CURSORDOWN 2
#define CODE_CURSORLEFT 3 #define TTY_CURSORRIGHT 3
#define CODE_INSERTCHARACTER 4 #define TTY_CURSORLEFT 4
#define CODE_DELETECHARACTER 5 #define TTY_INSERTCHARACTER 5
#define CODE_INSERTLINE 6 #define TTY_DELETECHARACTER 6
#define CODE_DELETELINE 7 #define TTY_INSERTLINE 7
#define CODE_CLEARLINE 8 #define TTY_DELETELINE 8
/* 9 unused */ #define TTY_CLEARLINE 9
/* 10 unused */ #define TTY_CLEARENDOFLINE 10
#define CODE_CLEARENDOFLINE 11 #define TTY_CLEARSTARTOFLINE 11
#define CODE_CLEARSTARTOFLINE 12 #define TTY_CURSORMOVE 12
#define CODE_CURSORMOVE 13 #define TTY_ATTRIBUTES 13
#define CODE_ATTRIBUTES 14 #define TTY_CURSOROFF 14
#define CODE_CURSOROFF 15 #define TTY_CURSORON 15
#define CODE_CURSORON 16 #define TTY_REVERSEINDEX 16
#define CODE_REVERSEINDEX 17 #define TTY_SCROLLREGION 17
/* 18 unused */ #define TTY_INSERTON 18
#define CODE_SCROLLREGION 19 #define TTY_INSERTOFF 19
#define CODE_INSERTON 20 #define TTY_KCURSOROFF 20
#define CODE_INSERTOFF 21 #define TTY_KCURSORON 21
#define CODE_KCURSOROFF 22 #define TTY_KKEYPADOFF 22
#define CODE_KCURSORON 23 #define TTY_KKEYPADON 23
#define CODE_KKEYPADOFF 24 #define TTY_TITLE 24
#define CODE_KKEYPADON 25
#define CODE_TITLE 26
/* Message codes. */ /* Message codes. */
enum hdrtype { enum hdrtype {
@ -294,9 +293,6 @@ enum hdrtype {
MSG_READY, MSG_READY,
MSG_DETACH, MSG_DETACH,
MSG_RESIZE, MSG_RESIZE,
MSG_DATA,
MSG_KEYS,
MSG_PAUSE,
}; };
/* Message header structure. */ /* Message header structure. */
@ -317,6 +313,8 @@ struct msg_identify_data {
u_int sx; u_int sx;
u_int sy; u_int sy;
size_t termlen;
}; };
struct msg_resize_data { struct msg_resize_data {
@ -394,8 +392,10 @@ struct screen_draw_sel {
/* Screen redraw context. */ /* Screen redraw context. */
struct screen_draw_ctx { struct screen_draw_ctx {
void *data;
void (*write)(void *, int, ...);
struct screen *s; struct screen *s;
struct buffer *b;
u_int cx; u_int cx;
u_int cy; 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_y(s, y) ((y) < screen_size_y(s))
#define screen_in_region(s, y) ((y) >= (s)->rupper && (y) <= (s)->rlower) #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. */ /* Screen default contents. */
#define SCREEN_DEFDATA ' ' #define SCREEN_DEFDATA ' '
#define SCREEN_DEFATTR 0 #define SCREEN_DEFATTR 0
@ -439,7 +437,6 @@ struct input_arg {
/* Input parser context. */ /* Input parser context. */
struct input_ctx { struct input_ctx {
struct window *w; struct window *w;
struct buffer *b;
u_char *buf; u_char *buf;
size_t len; size_t len;
@ -462,7 +459,8 @@ struct input_ctx {
struct window_mode { struct window_mode {
void (*init)(struct window *); void (*init)(struct window *);
void (*resize)(struct window *, u_int, u_int); 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); void (*key)(struct window *, int);
}; };
@ -516,19 +514,49 @@ struct session {
}; };
ARRAY_DECL(sessions, struct session *); ARRAY_DECL(sessions, struct session *);
/* Client connection. */ /* TTY information. */
struct client { struct tty_key {
char *tty; int code;
char *string;
RB_ENTRY(tty_key) entry;
};
struct tty {
char *path;
char *term;
TERMINAL *termp;
int fd; int fd;
struct buffer *in; struct buffer *in;
struct buffer *out; 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 sx;
u_int sy; u_int sy;
#define CLIENT_TERMINAL 0x1 #define CLIENT_TERMINAL 0x1
#define CLIENT_PREFIX 0x2 #define CLIENT_PREFIX 0x2
#define CLIENT_ATTACHED 0x4
int flags; int flags;
struct session *session; struct session *session;
@ -541,13 +569,8 @@ struct client_ctx {
struct buffer *srv_in; struct buffer *srv_in;
struct buffer *srv_out; struct buffer *srv_out;
int loc_fd; #define CCTX_DETACH 0x1
struct buffer *loc_in; #define CCTX_EXIT 0x2
struct buffer *loc_out;
#define CCTX_PAUSE 0x1
#define CCTX_DETACH 0x2
#define CCTX_EXIT 0x4
int flags; int flags;
}; };
@ -629,6 +652,28 @@ void logfile(const char *);
void siginit(void); void siginit(void);
void sigreset(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 */ /* cmd.c */
struct cmd *cmd_parse(int, char **, char **); struct cmd *cmd_parse(int, char **, char **);
void cmd_exec(struct cmd *, struct cmd_ctx *); void cmd_exec(struct cmd *, struct cmd_ctx *);
@ -708,25 +753,23 @@ void server_write_client(
struct client *, enum hdrtype, const void *, size_t); struct client *, enum hdrtype, const void *, size_t);
void server_write_session( void server_write_session(
struct session *, enum hdrtype, const void *, size_t); 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); 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_clear_client(struct client *);
void server_redraw_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_redraw_session(struct session *);
void server_status_window_cur(struct window *); void server_status_session(struct session *);
void server_status_window_all(struct window *); void server_clear_window(struct window *);
void server_clear_window_cur(struct window *); void server_redraw_window(struct window *);
void server_clear_window_all(struct window *); void server_status_window(struct window *);
void server_redraw_window_cur(struct window *);
void server_redraw_window_all(struct window *);
void printflike2 server_write_message(struct client *, const char *, ...); void printflike2 server_write_message(struct client *, const char *, ...);
/* status.c */ /* 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 */ /* resize.c */
void recalculate_sizes(void); void recalculate_sizes(void);
@ -734,17 +777,10 @@ void recalculate_sizes(void);
/* input.c */ /* input.c */
void input_init(struct window *); void input_init(struct window *);
void input_free(struct window *); void input_free(struct window *);
void input_parse(struct window *, struct buffer *); void input_parse(struct window *);
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);
/* input-key.c */ /* input-key.c */
void input_key(struct buffer *, int); void input_key(struct window *, int);
/* screen-display.c */ /* screen-display.c */
void screen_display_make_lines(struct screen *, u_int, u_int); 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( void screen_get_cell(
struct screen *, u_int, u_int, u_char *, u_char *, u_char *); 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_set_cell(struct screen *, u_int, u_int, u_char, u_char, u_char);
void screen_draw_start(struct screen_draw_ctx *, void screen_draw_start_window(
struct screen *, struct buffer *, u_int, u_int); 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_stop(struct screen_draw_ctx *);
void screen_draw_set_selection( void screen_draw_set_selection(
struct screen_draw_ctx *, int, u_int, u_int, u_int, u_int); 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); int screen_draw_check_selection(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_get_cell(struct screen_draw_ctx *, void screen_draw_get_cell(struct screen_draw_ctx *,
u_int, u_int, u_char *, u_char *, u_char *); 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_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_cell(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_cells(struct screen_draw_ctx *, u_int, 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( void screen_fill_cells(
struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); 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 */ /* window.c */
extern struct windows windows; extern struct windows windows;
int window_cmp(struct window *, struct window *); 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); const char *, const char *, const char **, u_int, u_int);
void window_destroy(struct window *); void window_destroy(struct window *);
int window_resize(struct window *, u_int, u_int); int window_resize(struct window *, u_int, u_int);
void window_parse(struct window *, struct buffer *); void window_parse(struct window *);
void window_draw(struct window *, struct buffer *, u_int, u_int); void window_draw(
struct window *, struct screen_draw_ctx *, u_int, u_int);
void window_key(struct window *, int); void window_key(struct window *, int);
/* window-copy.c */ /* 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_delete_range(struct buffer *, size_t, size_t);
void buffer_write(struct buffer *, const void *, size_t); void buffer_write(struct buffer *, const void *, size_t);
void buffer_read(struct buffer *, 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 */ /* buffer-poll.c */
int buffer_poll(struct pollfd *, struct buffer *, struct buffer *); int buffer_poll(struct pollfd *, struct buffer *, struct buffer *);
void buffer_flush(int, struct buffer *n, struct buffer *);
/* log.c */ /* log.c */
void log_open(FILE *, int, int); void log_open(FILE *, int, int);

273
tty-keys.c Normal file
View File

@ -0,0 +1,273 @@
/* $Id: tty-keys.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include <string.h>
#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);
}

107
tty-write.c Normal file
View File

@ -0,0 +1,107 @@
/* $Id: tty-write.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#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);
}
}

401
tty.c Normal file
View File

@ -0,0 +1,401 @@
/* $Id: tty.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include <sys/ioctl.h>
#include <curses.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#define TTYDEFCHARS
/* glibc requires unistd.h before termios.h for TTYDEFCHARS. */
#include <unistd.h>
#include <termios.h>
#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;
}

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,7 +24,8 @@
void window_copy_init(struct window *); void window_copy_init(struct window *);
void window_copy_resize(struct window *, u_int, u_int); 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_key(struct window *, int);
void window_copy_draw_position(struct window *, struct screen_draw_ctx *); 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_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); screen_draw_set_attributes(ctx, 0, status_colour);
buffer_write(ctx->b, ptr, len); screen_draw_write_string(ctx, "%s", ptr);
} }
void 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 window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen; struct screen *s = &w->screen;
struct screen_draw_ctx ctx;
if (s->hsize != data->size) { if (s->hsize != data->size) {
data->oy += s->hsize - data->size; data->oy += s->hsize - data->size;
data->size = s->hsize; 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) if (py != 0)
screen_draw_lines(&ctx, py, ny); screen_draw_lines(ctx, py, ny);
else if (ny > 1) else {
screen_draw_lines(&ctx, py + 1, ny - 1); if (ny > 1)
screen_draw_lines(ctx, py + 1, ny - 1);
window_copy_draw_position(w, ctx);
}
if (py == 0) window_copy_move_cursor(w);
window_copy_draw_position(w, &ctx);
screen_draw_stop(&ctx);
input_store_two(b, CODE_CURSORMOVE, data->cy + 1, data->cx + 1);
} }
void void
@ -205,7 +201,7 @@ window_copy_key(struct window *w, int key)
return; return;
} }
if (data->oy != oy) { if (data->oy != oy) {
server_redraw_window_all(w); server_redraw_window(w);
window_copy_move_cursor(w); window_copy_move_cursor(w);
} }
return; return;
@ -217,7 +213,7 @@ done:
w->screen.mode &= ~MODE_BACKGROUND; w->screen.mode &= ~MODE_BACKGROUND;
recalculate_sizes(); recalculate_sizes();
server_redraw_window_all(w); server_redraw_window(w);
} }
void void
@ -322,30 +318,8 @@ void
window_copy_move_cursor(struct window *w) window_copy_move_cursor(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; 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++) { tty_write_window(w, TTY_CURSORMOVE, data->cy, data->cx);
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);
}
} }
void void
@ -467,94 +441,47 @@ window_copy_cursor_down(struct window *w)
void void
window_copy_draw_lines(struct window *w, u_int py, u_int ny) window_copy_draw_lines(struct window *w, u_int py, u_int ny)
{ {
struct client *c; struct window_copy_mode_data *data = w->modedata;
struct buffer *b; struct screen_draw_ctx ctx;
u_int i;
struct hdr hdr;
size_t size;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); window_copy_draw(w, &ctx, py, ny);
if (c == NULL || c->session == NULL) screen_draw_stop(&ctx);
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);
}
} }
void void
window_copy_scroll_left(struct window *w, u_int nx) window_copy_scroll_left(struct window *w, u_int nx)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c; u_int i;
struct buffer *b;
u_int i, j;
struct hdr hdr;
size_t size;
if (data->ox > SHRT_MAX - nx) if (data->ox > SHRT_MAX - nx)
nx = SHRT_MAX - data->ox; nx = SHRT_MAX - data->ox;
if (nx == 0) if (nx == 0)
return; return;
data->ox += nx; data->ox += nx;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_set_selection(&ctx,
if (c == NULL || c->session == NULL) data->selflag, data->selx, data->sely,
continue; data->cx + data->ox, data->size + data->cy - data->oy);
if (!session_has(c->session, w)) for (i = 1; i < screen_size_y(&w->screen); i++) {
continue; screen_draw_move_cursor(&ctx, 0, i);
b = c->out; screen_draw_delete_characters(&ctx, nx);
}
buffer_ensure(b, sizeof hdr); for (i = 0; i < nx; i++)
buffer_add(b, sizeof hdr); screen_draw_column(&ctx, screen_last_x(&w->screen) - i);
size = BUFFER_USED(b); window_copy_draw_position(w, &ctx);
screen_draw_stop(&ctx);
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);
}
} }
void void
window_copy_scroll_right(struct window *w, u_int nx) window_copy_scroll_right(struct window *w, u_int nx)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c; u_int i;
struct buffer *b;
u_int i, j;
struct hdr hdr;
size_t size;
if (data->ox < nx) if (data->ox < nx)
nx = data->ox; nx = data->ox;
@ -562,48 +489,26 @@ window_copy_scroll_right(struct window *w, u_int nx)
return; return;
data->ox -= nx; data->ox -= nx;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_set_selection(&ctx,
if (c == NULL || c->session == NULL) data->selflag, data->selx, data->sely,
continue; data->cx + data->ox, data->size + data->cy - data->oy);
if (!session_has(c->session, w)) for (i = 1; i < screen_size_y(&w->screen); i++) {
continue; screen_draw_move_cursor(&ctx, 0, i);
b = c->out; screen_draw_insert_characters(&ctx, nx);
}
buffer_ensure(b, sizeof hdr); for (i = 0; i < nx; i++)
buffer_add(b, sizeof hdr); screen_draw_column(&ctx, i);
size = BUFFER_USED(b); window_copy_draw_position(w, &ctx);
screen_draw_stop(&ctx);
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);
}
} }
void void
window_copy_scroll_up(struct window *w, u_int ny) window_copy_scroll_up(struct window *w, u_int ny)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i; u_int i;
struct hdr hdr;
size_t size;
if (data->oy < ny) if (data->oy < ny)
ny = data->oy; ny = data->oy;
@ -611,47 +516,26 @@ window_copy_scroll_up(struct window *w, u_int ny)
return; return;
data->oy -= ny; data->oy -= ny;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_set_selection(&ctx,
if (c == NULL || c->session == NULL) data->selflag, data->selx, data->sely,
continue; data->cx + data->ox, data->size + data->cy - data->oy);
if (!session_has(c->session, w)) screen_draw_move_cursor(&ctx, 0, 0);
continue; screen_draw_delete_lines(&ctx, ny);
for (i = 0; i < ny; i++)
buffer_ensure(c->out, sizeof hdr); screen_draw_line(&ctx, screen_last_y(&w->screen) - i);
buffer_add(c->out, sizeof hdr); if (data->selflag)
size = BUFFER_USED(c->out); screen_draw_line(&ctx, screen_last_y(&w->screen) - ny);
window_copy_draw_position(w, &ctx);
screen_draw_start(&ctx, s, c->out, data->ox, data->oy); screen_draw_stop(&ctx);
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);
}
} }
void void
window_copy_scroll_down(struct window *w, u_int ny) window_copy_scroll_down(struct window *w, u_int ny)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i; u_int i;
struct hdr hdr;
size_t size;
if (ny > data->size) if (ny > data->size)
return; return;
@ -662,31 +546,14 @@ window_copy_scroll_down(struct window *w, u_int ny)
return; return;
data->oy += ny; data->oy += ny;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_set_selection(&ctx,
if (c == NULL || c->session == NULL) data->selflag, data->selx, data->sely,
continue; data->cx + data->ox, data->size + data->cy - data->oy);
if (!session_has(c->session, w)) screen_draw_move_cursor(&ctx, 0, 0);
continue; screen_draw_insert_lines(&ctx, ny);
for (i = 1; i < ny + 1; i++)
buffer_ensure(c->out, sizeof hdr); screen_draw_line(&ctx, i);
buffer_add(c->out, sizeof hdr); window_copy_draw_position(w, &ctx);
size = BUFFER_USED(c->out); screen_draw_stop(&ctx);
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);
}
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,7 +24,8 @@
void window_more_init(struct window *); void window_more_init(struct window *);
void window_more_resize(struct window *, u_int, u_int); 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_key(struct window *, int);
void window_more_draw_position(struct window *, struct screen_draw_ctx *); 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]; char *ptr, buf[32];
size_t len; size_t len;
char *line; char *line;
size_t n;
len = xsnprintf( len = xsnprintf(
buf, sizeof buf, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); 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); 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)) { if (data->top < ARRAY_LENGTH(&data->list)) {
line = ARRAY_ITEM(&data->list, data->top); line = xstrdup(ARRAY_ITEM(&data->list, data->top));
n = strlen(line); if (strlen(line) > screen_size_x(ctx->s) - len)
if (n > screen_size_x(ctx->s) - len) line[screen_size_x(ctx->s) - len] = '\0';
n = screen_size_x(ctx->s) - len; screen_draw_write_string(ctx, "%s", line);
buffer_write(ctx->b, line, n); xfree(line);
} else }
n = 0; screen_draw_clear_line_to(ctx, screen_size_x(ctx->s) - len - 1);
for (; n < screen_size_x(ctx->s) - len; n++)
input_store8(ctx->b, SCREEN_DEFDATA);
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); screen_draw_set_attributes(ctx, 0, status_colour);
buffer_write(ctx->b, buf, len); screen_draw_write_string(ctx, "%s", ptr);
} }
void void
window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py) window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
char *line;
size_t n;
u_int p; 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); screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
p = data->top + py; p = data->top + py;
if (p >= ARRAY_LENGTH(&data->list)) { if (p < ARRAY_LENGTH(&data->list))
input_store_zero(ctx->b, CODE_CLEARLINE); screen_draw_write_string(ctx, "%s", ARRAY_ITEM(&data->list, p));
return;
}
line = ARRAY_ITEM(&data->list, p); screen_draw_clear_line_to(ctx, screen_last_x(ctx->s));
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);
} }
void 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; u_int i;
struct screen_draw_ctx ctx;
u_int i;
screen_draw_start(&ctx, s, b, 0, 0);
for (i = py; i < py + ny; i++) { for (i = py; i < py + ny; i++) {
if (i == 0) if (i == 0)
continue; window_more_draw_position(w, ctx);
window_more_draw_line(w, &ctx, i); else
window_more_draw_line(w, ctx, i);
} }
if (py == 0)
window_more_draw_position(w, &ctx);
screen_draw_stop(&ctx);
} }
void void
@ -189,7 +170,7 @@ window_more_key(struct window *w, int key)
w->screen.mode &= ~MODE_BACKGROUND; w->screen.mode &= ~MODE_BACKGROUND;
recalculate_sizes(); recalculate_sizes();
server_redraw_window_all(w); server_redraw_window(w);
return; return;
case 'k': case 'k':
case 'K': case 'K':
@ -217,47 +198,25 @@ window_more_key(struct window *w, int key)
break; break;
} }
if (top != data->top) if (top != data->top)
server_redraw_window_all(w); server_redraw_window(w);
} }
void void
window_more_up_1(struct window *w) window_more_up_1(struct window *w)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->top == 0) if (data->top == 0)
return; return;
data->top--; data->top--;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, 0, 0);
c = ARRAY_ITEM(&clients, i); screen_draw_move_cursor(&ctx, 0, 0);
if (c == NULL || c->session == NULL) screen_draw_insert_lines(&ctx, 1);
continue; window_more_draw_position(w, &ctx);
if (!session_has(c->session, w)) window_more_draw_line(w, &ctx, 1);
continue; screen_draw_stop(&ctx);
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);
}
} }
void void
@ -266,36 +225,15 @@ window_more_down_1(struct window *w)
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
struct screen *s = &w->screen; struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->top >= ARRAY_LENGTH(&data->list)) if (data->top >= ARRAY_LENGTH(&data->list))
return; return;
data->top++; data->top++;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, 0, 0);
c = ARRAY_ITEM(&clients, i); screen_draw_move_cursor(&ctx, 0, 0);
if (c == NULL || c->session == NULL) screen_draw_delete_lines(&ctx, 1);
continue; window_more_draw_line(w, &ctx, screen_last_y(s));
if (!session_has(c->session, w)) window_more_draw_position(w, &ctx);
continue; screen_draw_stop(&ctx);
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);
}
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,7 +24,8 @@
void window_scroll_init(struct window *); void window_scroll_init(struct window *);
void window_scroll_resize(struct window *, u_int, u_int); 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_key(struct window *, int);
void window_scroll_draw_position(struct window *, struct screen_draw_ctx *); 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_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); screen_draw_set_attributes(ctx, 0, status_colour);
buffer_write(ctx->b, ptr, len);
} }
void 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 window_scroll_mode_data *data = w->modedata;
struct screen *s = &w->screen; struct screen *s = &w->screen;
struct screen_draw_ctx ctx;
if (s->hsize != data->size) { if (s->hsize != data->size) {
data->oy += s->hsize - data->size; data->oy += s->hsize - data->size;
data->size = s->hsize; data->size = s->hsize;
} }
screen_draw_start(&ctx, s, b, data->ox, data->oy);
if (py != 0) if (py != 0)
screen_draw_lines(&ctx, py, ny); screen_draw_lines(ctx, py, ny);
else if (ny > 1) else {
screen_draw_lines(&ctx, py + 1, ny - 1); if (ny > 1)
screen_draw_lines(ctx, py + 1, ny - 1);
if (py == 0) window_scroll_draw_position(w, ctx);
window_scroll_draw_position(w, &ctx); }
screen_draw_stop(&ctx);
} }
void void
@ -133,7 +130,7 @@ window_scroll_key(struct window *w, int key)
w->screen.mode &= ~MODE_BACKGROUND; w->screen.mode &= ~MODE_BACKGROUND;
recalculate_sizes(); recalculate_sizes();
server_redraw_window_all(w); server_redraw_window(w);
return; return;
case 'h': case 'h':
case KEYC_LEFT: case KEYC_LEFT:
@ -169,169 +166,84 @@ window_scroll_key(struct window *w, int key)
break; break;
} }
if (ox != data->ox || oy != data->oy) if (ox != data->ox || oy != data->oy)
server_redraw_window_all(w); server_redraw_window(w);
} }
void void
window_scroll_up_1(struct window *w) window_scroll_up_1(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->oy >= data->size) if (data->oy >= data->size)
return; return;
data->oy++; data->oy++;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_move_cursor(&ctx, 0, 0);
if (c == NULL || c->session == NULL) screen_draw_insert_lines(&ctx, 1);
continue; window_scroll_draw_position(w, &ctx);
if (!session_has(c->session, w)) screen_draw_line(&ctx, 1);
continue; screen_draw_stop(&ctx);
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);
}
} }
void void
window_scroll_down_1(struct window *w) window_scroll_down_1(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->oy == 0) if (data->oy == 0)
return; return;
data->oy--; data->oy--;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); screen_draw_move_cursor(&ctx, 0, 0);
if (c == NULL || c->session == NULL) screen_draw_delete_lines(&ctx, 1);
continue; screen_draw_line(&ctx, screen_last_y(&w->screen));
if (!session_has(c->session, w)) window_scroll_draw_position(w, &ctx);
continue; screen_draw_stop(&ctx);
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);
}
} }
void void
window_scroll_right_1(struct window *w) window_scroll_right_1(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c; u_int i;
u_int i, j;
struct hdr hdr;
size_t size;
if (data->ox >= SHRT_MAX) if (data->ox >= SHRT_MAX)
return; return;
data->ox++; data->ox++;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { screen_draw_start_window(&ctx, w, data->ox, data->oy);
c = ARRAY_ITEM(&clients, i); for (i = 1; i < screen_size_y(&w->screen); i++) {
if (c == NULL || c->session == NULL) screen_draw_move_cursor(&ctx, 0, i);
continue; screen_draw_delete_characters(&ctx, 1);
if (!session_has(c->session, w)) }
continue; screen_draw_column(&ctx, screen_last_x(&w->screen));
window_scroll_draw_position(w, &ctx);
buffer_ensure(c->out, sizeof hdr); screen_draw_stop(&ctx);
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);
}
} }
void void
window_scroll_left_1(struct window *w) window_scroll_left_1(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx; struct screen_draw_ctx ctx;
struct client *c; u_int i;
u_int i, j;
struct hdr hdr;
size_t size;
if (data->ox == 0) if (data->ox == 0)
return; return;
data->ox--; 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); screen_draw_start_window(&ctx, w, data->ox, data->oy);
buffer_add(c->out, sizeof hdr); for (i = 1; i < screen_size_y(&w->screen); i++) {
size = BUFFER_USED(c->out); screen_draw_move_cursor(&ctx, 0, i);
screen_draw_insert_characters(&ctx, 1);
screen_draw_start(&ctx, s, c->out, data->ox, data->oy); }
for (j = 1; j < screen_size_y(s); j++) { screen_draw_column(&ctx, 0);
screen_draw_move(&ctx, 0, j); window_scroll_draw_position(w, &ctx);
input_store_one(c->out, CODE_INSERTCHARACTER, 1); screen_draw_stop(&ctx);
}
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);
}
} }

View File

@ -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 <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -274,24 +274,18 @@ window_resize(struct window *w, u_int sx, u_int sy)
} }
void void
window_parse(struct window *w, struct buffer *b) window_parse(struct window *w)
{ {
input_parse(w, b); input_parse(w);
} }
void 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) if (w->mode != NULL)
w->mode->draw(w, b, py, ny); w->mode->draw(w, ctx, py, ny);
else { else
screen_draw_start(&ctx, s, b, 0, 0); screen_draw_lines(ctx, py, ny);
screen_draw_lines(&ctx, py, ny);
screen_draw_stop(&ctx);
}
} }
void void
@ -300,5 +294,5 @@ window_key(struct window *w, int key)
if (w->mode != NULL) if (w->mode != NULL)
w->mode->key(w, key); w->mode->key(w, key);
else else
input_key(w->out, key); input_key(w, key);
} }