Major reorganisation of screen handling.

This commit is contained in:
Nicholas Marriott 2007-12-06 09:46:23 +00:00
parent 6f142e9ac6
commit 103748d6ad
52 changed files with 2084 additions and 1538 deletions

10
CHANGES
View File

@ -1,3 +1,11 @@
06 December 2007
* Another major reorganisation, this time of screen handling. A new set of
functions, screen_write_*, are now used to write to a screen and a tty
simultaneously. These are used by the input parser to update the base
window screen and also by the different modes which now interpose their own
screen.
30 November 2007 30 November 2007
* Support \ek...\e\ to set window name. * Support \ek...\e\ to set window name.
@ -289,4 +297,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.89 2007-11-30 11:08:34 nicm Exp $ $Id: CHANGES,v 1.90 2007-12-06 09:46:21 nicm Exp $

View File

@ -1,4 +1,4 @@
# $Id: GNUmakefile,v 1.8 2007-11-25 22:08:13 nicm Exp $ # $Id: GNUmakefile,v 1.9 2007-12-06 09:46:21 nicm Exp $
.PHONY: clean .PHONY: clean
@ -37,7 +37,7 @@ CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
LDFLAGS+= LDFLAGS+=
LIBS+= -lncurses LIBS+= -lncurses
PREFIX?= /usr/local PREFIX?= /usr/local

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.51 2007-11-30 13:59:16 nicm Exp $ # $Id: Makefile,v 1.52 2007-12-06 09:46:21 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
@ -28,7 +28,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.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 tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c
CC?= cc CC?= cc
INCDIRS+= -I. -I- -I/usr/local/include INCDIRS+= -I. -I- -I/usr/local/include

16
TODO
View File

@ -66,13 +66,27 @@
-- For 0.2 -------------------------------------------------------------------- -- For 0.2 --------------------------------------------------------------------
- window splitting? - window splitting?
- restore term cap checks - restore term cap checks ****
- anything which uses cmd_{send,recv}_string will break if the string is - anything which uses cmd_{send,recv}_string will break if the string is
split. string length should be part of the command size split. string length should be part of the command size
- echo \\033[35\;46m\\033[2J last line quirk (with C-b r) - echo \\033[35\;46m\\033[2J last line quirk (with C-b r)
- quick intro section (tmux new/attach/detach) etc - quick intro section (tmux new/attach/detach) etc
- is ACS the right way round?? - is ACS the right way round??
--------
screen redraw.
ops:
- redraw screen or section of screen to tty without altering it
(screen-redraw.c, screen_redraw_ctx)
(switching screen etc)
- draw to screen and optionally tty
(window output)
(screen-write.c, screen_write_ctx)
- copy line/column from one screen (inc history) at offset??
(scroll/copy mode)
-------- --------
kmous -- \E[M kmous -- \E[M

View File

@ -1,4 +1,4 @@
/* $Id: buffer.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: buffer.c,v 1.4 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -215,7 +215,7 @@ uint16_t
buffer_read16(struct buffer *b) buffer_read16(struct buffer *b)
{ {
uint16_t n; uint16_t n;
n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8); n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8);
buffer_remove(b, 2); buffer_remove(b, 2);
return (n); return (n);

View File

@ -1,4 +1,4 @@
/* $Id: client-msg.c,v 1.13 2007-11-27 20:03:08 nicm Exp $ */ /* $Id: client-msg.c,v 1.14 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -34,7 +34,7 @@ int client_msg_fn_pause(struct hdr *, struct client_ctx *, char **);
struct client_msg { struct client_msg {
enum hdrtype type; enum hdrtype type;
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[] = {
@ -58,7 +58,7 @@ client_msg_dispatch(struct client_ctx *cctx, char **error)
if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size) if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size)
return (1); return (1);
buffer_remove(cctx->srv_in, sizeof hdr); buffer_remove(cctx->srv_in, sizeof hdr);
for (i = 0; i < NCLIENTMSG; i++) { for (i = 0; i < NCLIENTMSG; i++) {
msg = client_msg_table + i; msg = client_msg_table + i;
if (msg->type == hdr.type) { if (msg->type == hdr.type) {
@ -92,7 +92,7 @@ client_msg_fn_detach(
client_write_server(cctx, MSG_EXITING, NULL, 0); client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_DETACH; cctx->flags |= CCTX_DETACH;
return (0); return (0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: client.c,v 1.24 2007-12-01 11:10:33 nicm Exp $ */ /* $Id: client.c,v 1.25 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -134,7 +134,7 @@ client_main(struct client_ctx *cctx)
pfd.events = POLLIN; pfd.events = POLLIN;
if (BUFFER_USED(cctx->srv_out) > 0) if (BUFFER_USED(cctx->srv_out) > 0)
pfd.events |= POLLOUT; pfd.events |= POLLOUT;
if (poll(&pfd, 1, timeout) == -1) { if (poll(&pfd, 1, timeout) == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
@ -157,18 +157,18 @@ client_main(struct client_ctx *cctx)
break; break;
} }
} }
out: out:
if (sigterm) { if (sigterm) {
printf("[terminated]\n"); printf("[terminated]\n");
return (1); return (1);
} }
if (cctx->flags & CCTX_EXIT) { if (cctx->flags & CCTX_EXIT) {
printf("[exited]\n"); printf("[exited]\n");
return (0); return (0);
} }
if (cctx->flags & CCTX_DETACH) { if (cctx->flags & CCTX_DETACH) {
printf("[detached]\n"); printf("[detached]\n");
return (0); return (0);
@ -187,13 +187,13 @@ client_handle_winch(struct client_ctx *cctx)
{ {
struct msg_resize_data data; struct msg_resize_data data;
struct winsize ws; struct winsize ws;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl failed"); fatal("ioctl failed");
data.sx = ws.ws_col; data.sx = ws.ws_col;
data.sy = ws.ws_row; data.sy = ws.ws_row;
client_write_server(cctx, MSG_RESIZE, &data, sizeof data); client_write_server(cctx, MSG_RESIZE, &data, sizeof data);
sigwinch = 0; sigwinch = 0;
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-attach-session.c,v 1.10 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: cmd-attach-session.c,v 1.11 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -40,7 +40,7 @@ const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "[-d]", "attach-session", "attach", "[-d]",
CMD_CANTNEST|CMD_NOCLIENT, CMD_CANTNEST|CMD_NOCLIENT,
cmd_attach_session_parse, cmd_attach_session_parse,
cmd_attach_session_exec, cmd_attach_session_exec,
cmd_attach_session_send, cmd_attach_session_send,
cmd_attach_session_recv, cmd_attach_session_recv,
cmd_attach_session_free cmd_attach_session_free
@ -63,7 +63,7 @@ cmd_attach_session_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 0) if (argc != 0)

View File

@ -1,4 +1,4 @@
/* $Id: cmd-bind-key.c,v 1.7 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-bind-key.c,v 1.8 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,7 +41,7 @@ const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "key command [arguments]", "bind-key", "bind", "key command [arguments]",
CMD_NOCLIENT|CMD_NOSESSION, CMD_NOCLIENT|CMD_NOSESSION,
cmd_bind_key_parse, cmd_bind_key_parse,
cmd_bind_key_exec, cmd_bind_key_exec,
cmd_bind_key_send, cmd_bind_key_send,
cmd_bind_key_recv, cmd_bind_key_recv,
cmd_bind_key_free cmd_bind_key_free
@ -61,7 +61,7 @@ cmd_bind_key_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc < 1) if (argc < 1)

View File

@ -1,4 +1,4 @@
/* $Id: cmd-copy-mode.c,v 1.2 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: cmd-copy-mode.c,v 1.3 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,7 +33,7 @@ const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL, "", "copy-mode", NULL, "",
CMD_NOCLIENT, CMD_NOCLIENT,
NULL, NULL,
cmd_copy_mode_exec, cmd_copy_mode_exec,
NULL, NULL,
NULL, NULL,
NULL NULL

View File

@ -1,4 +1,4 @@
/* $Id: cmd-kill-session.c,v 1.4 2007-11-21 13:11:41 nicm Exp $ */ /* $Id: cmd-kill-session.c,v 1.5 2007-12-06 09:46:21 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_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx)
{ {
struct client *c; struct client *c;
u_int i; u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
if (c->session == ctx->session) { if (c->session == ctx->session) {
@ -57,7 +57,7 @@ cmd_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx)
} }
session_destroy(ctx->session); session_destroy(ctx->session);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-kill-window.c,v 1.6 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-kill-window.c,v 1.7 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,7 +41,7 @@ const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw", "[-i index]", "kill-window", "killw", "[-i index]",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_kill_window_parse, cmd_kill_window_parse,
cmd_kill_window_exec, cmd_kill_window_exec,
cmd_kill_window_send, cmd_kill_window_send,
cmd_kill_window_recv, cmd_kill_window_recv,
cmd_kill_window_free cmd_kill_window_free
@ -69,7 +69,7 @@ cmd_kill_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 0) if (argc != 0)
@ -117,7 +117,7 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx)
} else } else
server_redraw_client(c); server_redraw_client(c);
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-last-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-last-window.c,v 1.6 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -45,8 +45,8 @@ cmd_last_window_exec(unused void *ptr, struct cmd_ctx *ctx)
if (session_last(ctx->session) == 0) if (session_last(ctx->session) == 0)
server_redraw_session(ctx->session); server_redraw_session(ctx->session);
else else
ctx->error(ctx, "no last window"); ctx->error(ctx, "no last window");
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-link-window.c,v 1.8 2007-11-21 15:05:53 nicm Exp $ */ /* $Id: cmd-link-window.c,v 1.9 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -45,7 +45,7 @@ const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw", "[-dk] [-i index] name index", "link-window", "linkw", "[-dk] [-i index] name index",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_link_window_parse, cmd_link_window_parse,
cmd_link_window_exec, cmd_link_window_exec,
cmd_link_window_send, cmd_link_window_send,
cmd_link_window_recv, cmd_link_window_recv,
cmd_link_window_free cmd_link_window_free
@ -83,7 +83,7 @@ cmd_link_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 2) if (argc != 2)
@ -116,7 +116,7 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return; return;
if ((src = session_find(data->srcname)) == NULL) { if ((src = session_find(data->srcname)) == NULL) {
ctx->error(ctx, "session not found: %s", data->srcname); ctx->error(ctx, "session not found: %s", data->srcname);
return; return;
@ -155,7 +155,7 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx)
dst->lastw = NULL; dst->lastw = NULL;
/* /*
* Can't error out after this or there could be an empty * Can't error out after this or there could be an empty
* session! * session!
*/ */
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.14 2007-11-23 13:11:43 nicm Exp $ */ /* $Id: cmd-list-windows.c,v 1.15 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -51,18 +51,18 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx)
w = wl->window; w = wl->window;
size = 0; size = 0;
for (i = 0; i < w->screen.hsize; i++) for (i = 0; i < w->base.hsize; i++)
size += w->screen.grid_size[i] * 3; size += w->base.grid_size[i] * 3;
size += w->screen.hsize * (sizeof *w->screen.grid_data); size += w->base.hsize * (sizeof *w->base.grid_data);
size += w->screen.hsize * (sizeof *w->screen.grid_attr); size += w->base.hsize * (sizeof *w->base.grid_attr);
size += w->screen.hsize * (sizeof *w->screen.grid_colr); size += w->base.hsize * (sizeof *w->base.grid_colr);
size += w->screen.hsize * (sizeof *w->screen.grid_size); size += w->base.hsize * (sizeof *w->base.grid_size);
ctx->print(ctx, ctx->print(ctx,
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]", "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]",
wl->idx, w->name, w->screen.title, ttyname(w->fd), wl->idx, w->name, w->base.title, ttyname(w->fd),
screen_size_x(&w->screen), screen_size_y(&w->screen), screen_size_x(&w->base), screen_size_y(&w->base),
w->screen.hsize, w->screen.hlimit, size); w->base.hsize, w->base.hlimit, size);
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)

View File

@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.18 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: cmd-new-session.c,v 1.19 2007-12-06 09:46:21 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -44,7 +44,7 @@ const struct cmd_entry cmd_new_session_entry = {
"[-d] [-s session-name] [-n window-name] [command]", "[-d] [-s session-name] [-n window-name] [command]",
CMD_STARTSERVER|CMD_NOCLIENT|CMD_NOSESSION|CMD_CANTNEST, CMD_STARTSERVER|CMD_NOCLIENT|CMD_NOSESSION|CMD_CANTNEST,
cmd_new_session_parse, cmd_new_session_parse,
cmd_new_session_exec, cmd_new_session_exec,
cmd_new_session_send, cmd_new_session_send,
cmd_new_session_recv, cmd_new_session_recv,
cmd_new_session_free cmd_new_session_free
@ -76,7 +76,7 @@ cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 0 && argc != 1) if (argc != 0 && argc != 1)
@ -90,7 +90,7 @@ cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause)
usage: usage:
usage(cause, "%s %s", usage(cause, "%s %s",
cmd_new_session_entry.name, cmd_new_session_entry.usage); cmd_new_session_entry.name, cmd_new_session_entry.usage);
cmd_new_session_free(data); cmd_new_session_free(data);
return (-1); return (-1);
} }
@ -103,7 +103,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
struct client *c = ctx->cmdclient; struct client *c = ctx->cmdclient;
char *cmd, *cause; char *cmd, *cause;
u_int sy; u_int sy;
if (data == NULL) if (data == NULL)
data = &std; data = &std;

View File

@ -1,4 +1,4 @@
/* $Id: cmd-new-window.c,v 1.13 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-new-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -44,7 +44,7 @@ const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "[-d] [-i index] [-n name] [command]", "new-window", "neww", "[-d] [-i index] [-n name] [command]",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_new_window_parse, cmd_new_window_parse,
cmd_new_window_exec, cmd_new_window_exec,
cmd_new_window_send, cmd_new_window_send,
cmd_new_window_recv, cmd_new_window_recv,
cmd_new_window_free cmd_new_window_free
@ -81,7 +81,7 @@ cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 0 && argc != 1) if (argc != 0 && argc != 1)
@ -111,7 +111,7 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
data = &std; data = &std;
cmd = data->cmd; cmd = data->cmd;
if (cmd == NULL) if (cmd == NULL)
cmd = default_command; cmd = default_command;
@ -128,7 +128,7 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
server_redraw_session(ctx->session); server_redraw_session(ctx->session);
} else } else
server_status_session(ctx->session); server_status_session(ctx->session);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-next-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-next-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -45,8 +45,8 @@ cmd_next_window_exec(unused void *ptr, struct cmd_ctx *ctx)
if (session_next(ctx->session) == 0) if (session_next(ctx->session) == 0)
server_redraw_session(ctx->session); server_redraw_session(ctx->session);
else else
ctx->error(ctx, "no next window"); ctx->error(ctx, "no next window");
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-paste-buffer.c,v 1.1 2007-11-23 17:52:54 nicm Exp $ */ /* $Id: cmd-paste-buffer.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -34,7 +34,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", NULL, "paste", "paste-buffer", NULL, "paste",
CMD_NOCLIENT, CMD_NOCLIENT,
NULL, NULL,
cmd_paste_buffer_exec, cmd_paste_buffer_exec,
NULL, NULL,
NULL, NULL,
NULL NULL

View File

@ -1,4 +1,4 @@
/* $Id: cmd-previous-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-previous-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -45,8 +45,8 @@ cmd_previous_window_exec(unused void *ptr, struct cmd_ctx *ctx)
if (session_previous(ctx->session) == 0) if (session_previous(ctx->session) == 0)
server_redraw_session(ctx->session); server_redraw_session(ctx->session);
else else
ctx->error(ctx, "no previous window"); ctx->error(ctx, "no previous window");
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-rename-session.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-rename-session.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,7 +41,7 @@ const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename", "new-name", "rename-session", "rename", "new-name",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_rename_session_parse, cmd_rename_session_parse,
cmd_rename_session_exec, cmd_rename_session_exec,
cmd_rename_session_send, cmd_rename_session_send,
cmd_rename_session_recv, cmd_rename_session_recv,
cmd_rename_session_free cmd_rename_session_free
@ -61,7 +61,7 @@ cmd_rename_session_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (argc != 1)
@ -89,7 +89,7 @@ cmd_rename_session_exec(void *ptr, struct cmd_ctx *ctx)
xfree(ctx->session->name); xfree(ctx->session->name);
ctx->session->name = xstrdup(data->newname); ctx->session->name = xstrdup(data->newname);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-rename-window.c,v 1.13 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-rename-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -42,7 +42,7 @@ const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew", "[-i index] new-name", "rename-window", "renamew", "[-i index] new-name",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_rename_window_parse, cmd_rename_window_parse,
cmd_rename_window_exec, cmd_rename_window_exec,
cmd_rename_window_send, cmd_rename_window_send,
cmd_rename_window_recv, cmd_rename_window_recv,
cmd_rename_window_free cmd_rename_window_free
@ -71,7 +71,7 @@ cmd_rename_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (argc != 1)
@ -110,7 +110,7 @@ cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx)
wl->window->name = xstrdup(data->newname); wl->window->name = xstrdup(data->newname);
server_status_session(ctx->session); server_status_session(ctx->session);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-scroll-mode.c,v 1.4 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: cmd-scroll-mode.c,v 1.5 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,7 +33,7 @@ const struct cmd_entry cmd_scroll_mode_entry = {
"scroll-mode", NULL, "", "scroll-mode", NULL, "",
CMD_NOCLIENT, CMD_NOCLIENT,
NULL, NULL,
cmd_scroll_mode_exec, cmd_scroll_mode_exec,
NULL, NULL,
NULL, NULL,
NULL NULL

View File

@ -1,4 +1,4 @@
/* $Id: cmd-select-window.c,v 1.10 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-select-window.c,v 1.11 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,7 +41,7 @@ const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw", "index", "select-window", "selectw", "index",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_select_window_parse, cmd_select_window_parse,
cmd_select_window_exec, cmd_select_window_exec,
cmd_select_window_send, cmd_select_window_send,
cmd_select_window_recv, cmd_select_window_recv,
cmd_select_window_free cmd_select_window_free
@ -75,7 +75,7 @@ cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (argc != 1)
@ -86,7 +86,7 @@ cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause)
xasprintf(cause, "index %s", errstr); xasprintf(cause, "index %s", errstr);
goto error; goto error;
} }
return (0); return (0);
usage: usage:
@ -116,7 +116,7 @@ cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx)
ctx->error(ctx, "no window %d", data->idx); ctx->error(ctx, "no window %d", data->idx);
break; break;
} }
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-send-prefix.c,v 1.6 2007-11-21 13:11:41 nicm Exp $ */ /* $Id: cmd-send-prefix.c,v 1.7 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -44,6 +44,6 @@ cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx)
{ {
window_key(ctx->client->session->curw->window, prefix_key); window_key(ctx->client->session->curw->window, prefix_key);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.14 2007-11-23 12:48:20 nicm Exp $ */ /* $Id: cmd-set-option.c,v 1.15 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -43,7 +43,7 @@ const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "option value", "set-option", "set", "option value",
CMD_NOCLIENT|CMD_NOSESSION, CMD_NOCLIENT|CMD_NOSESSION,
cmd_set_option_parse, cmd_set_option_parse,
cmd_set_option_exec, cmd_set_option_exec,
cmd_set_option_send, cmd_set_option_send,
cmd_set_option_recv, cmd_set_option_recv,
cmd_set_option_free cmd_set_option_free
@ -64,7 +64,7 @@ cmd_set_option_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1 && argc != 2) if (argc != 1 && argc != 2)
@ -104,7 +104,7 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
number = -1; number = -1;
if (data->value != NULL) { if (data->value != NULL) {
number = strtonum(data->value, 0, INT_MAX, &errstr); number = strtonum(data->value, 0, INT_MAX, &errstr);
bool = -1; bool = -1;
if (number == 1 || strcasecmp(data->value, "on") == 0 || if (number == 1 || strcasecmp(data->value, "on") == 0 ||
strcasecmp(data->value, "yes") == 0) strcasecmp(data->value, "yes") == 0)
@ -171,10 +171,10 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
server_redraw_client(c); server_redraw_client(c);
} }
} }
} else if (strcmp(data->option, "bell-action") == 0) { } else if (strcmp(data->option, "bell-action") == 0) {
if (data->value == NULL) { if (data->value == NULL) {
ctx->error(ctx, "invalid value"); ctx->error(ctx, "invalid value");
return; return;
} }
if (strcmp(data->value, "any") == 0) if (strcmp(data->value, "any") == 0)
bell_action = BELL_ANY; bell_action = BELL_ANY;
@ -186,10 +186,10 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
ctx->error(ctx, "unknown bell-action: %s", data->value); ctx->error(ctx, "unknown bell-action: %s", data->value);
return; return;
} }
} else if (strcmp(data->option, "default-command") == 0) { } else if (strcmp(data->option, "default-command") == 0) {
if (data->value == NULL) { if (data->value == NULL) {
ctx->error(ctx, "invalid value"); ctx->error(ctx, "invalid value");
return; return;
} }
xfree(default_command); xfree(default_command);
default_command = xstrdup(data->value); default_command = xstrdup(data->value);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-swap-window.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-swap-window.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -44,7 +44,7 @@ const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw", "[-i index] name index", "swap-window", "swapw", "[-i index] name index",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_swap_window_parse, cmd_swap_window_parse,
cmd_swap_window_exec, cmd_swap_window_exec,
cmd_swap_window_send, cmd_swap_window_send,
cmd_swap_window_recv, cmd_swap_window_recv,
cmd_swap_window_free cmd_swap_window_free
@ -78,7 +78,7 @@ cmd_swap_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 2) if (argc != 2)
@ -112,7 +112,7 @@ cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return; return;
if ((src = session_find(data->srcname)) == NULL) { if ((src = session_find(data->srcname)) == NULL) {
ctx->error(ctx, "session not found: %s", data->srcname); ctx->error(ctx, "session not found: %s", data->srcname);
return; return;

View File

@ -1,4 +1,4 @@
/* $Id: cmd-switch-client.c,v 1.1 2007-11-16 21:31:03 nicm Exp $ */ /* $Id: cmd-switch-client.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -42,7 +42,7 @@ const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "session-name", "switch-client", "switchc", "session-name",
CMD_NOSESSION, CMD_NOSESSION,
cmd_switch_client_parse, cmd_switch_client_parse,
cmd_switch_client_exec, cmd_switch_client_exec,
cmd_switch_client_send, cmd_switch_client_send,
cmd_switch_client_recv, cmd_switch_client_recv,
cmd_switch_client_free cmd_switch_client_free
@ -62,7 +62,7 @@ cmd_switch_client_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (argc != 1)
@ -88,14 +88,14 @@ cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return; return;
if ((s = session_find(data->name)) == NULL) { if ((s = session_find(data->name)) == NULL) {
ctx->error(ctx, "session not found: %s", data->name); ctx->error(ctx, "session not found: %s", data->name);
return; return;
} }
ctx->client->session = s; ctx->client->session = s;
recalculate_sizes(); recalculate_sizes();
server_redraw_client(ctx->client); server_redraw_client(ctx->client);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-unbind-key.c,v 1.7 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-unbind-key.c,v 1.8 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -40,7 +40,7 @@ const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "key", "unbind-key", "unbind", "key",
CMD_NOCLIENT|CMD_NOSESSION, CMD_NOCLIENT|CMD_NOSESSION,
cmd_unbind_key_parse, cmd_unbind_key_parse,
cmd_unbind_key_exec, cmd_unbind_key_exec,
cmd_unbind_key_send, cmd_unbind_key_send,
cmd_unbind_key_recv, cmd_unbind_key_recv,
cmd_unbind_key_free cmd_unbind_key_free
@ -59,7 +59,7 @@ cmd_unbind_key_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 1) if (argc != 1)

View File

@ -1,4 +1,4 @@
/* $Id: cmd-unlink-window.c,v 1.4 2007-11-16 21:12:31 nicm Exp $ */ /* $Id: cmd-unlink-window.c,v 1.5 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,7 +41,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw", "[-i index]", "unlink-window", "unlinkw", "[-i index]",
CMD_NOCLIENT, CMD_NOCLIENT,
cmd_unlink_window_parse, cmd_unlink_window_parse,
cmd_unlink_window_exec, cmd_unlink_window_exec,
cmd_unlink_window_send, cmd_unlink_window_send,
cmd_unlink_window_recv, cmd_unlink_window_recv,
cmd_unlink_window_free cmd_unlink_window_free
@ -69,7 +69,7 @@ cmd_unlink_window_parse(void **ptr, int argc, char **argv, char **cause)
default: default:
goto usage; goto usage;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc != 0) if (argc != 0)
@ -98,7 +98,7 @@ cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return; return;
if (data->idx < 0) if (data->idx < 0)
data->idx = -1; data->idx = -1;
if (data->idx == -1) if (data->idx == -1)

12
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.32 2007-11-23 17:52:54 nicm Exp $ */ /* $Id: cmd.c,v 1.33 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -48,7 +48,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_scroll_mode_entry, &cmd_scroll_mode_entry,
&cmd_select_window_entry, &cmd_select_window_entry,
&cmd_send_prefix_entry, &cmd_send_prefix_entry,
&cmd_set_option_entry, &cmd_set_option_entry,
&cmd_swap_window_entry, &cmd_swap_window_entry,
&cmd_switch_client_entry, &cmd_switch_client_entry,
&cmd_unbind_key_entry, &cmd_unbind_key_entry,
@ -70,7 +70,7 @@ cmd_parse(int argc, char **argv, char **cause)
entry = NULL; entry = NULL;
for (entryp = cmd_table; *entryp != NULL; entryp++) { for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL && if ((*entryp)->alias != NULL &&
strcmp((*entryp)->alias, argv[0]) == 0) { strcmp((*entryp)->alias, argv[0]) == 0) {
entry = *entryp; entry = *entryp;
break; break;
@ -165,7 +165,7 @@ cmd_recv(struct buffer *b)
u_int m, n; u_int m, n;
buffer_read(b, &m, sizeof m); buffer_read(b, &m, sizeof m);
n = 0; n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) { for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (n == m) if (n == m)
@ -195,7 +195,7 @@ void
cmd_send_string(struct buffer *b, const char *s) cmd_send_string(struct buffer *b, const char *s)
{ {
size_t n; size_t n;
if (s == NULL) { if (s == NULL) {
n = 0; n = 0;
buffer_write(b, &n, sizeof n); buffer_write(b, &n, sizeof n);
@ -218,7 +218,7 @@ cmd_recv_string(struct buffer *b)
if (n == 0) if (n == 0)
return (NULL); return (NULL);
s = xmalloc(n); s = xmalloc(n);
buffer_read(b, s, n); buffer_read(b, s, n);
s[n - 1] = '\0'; s[n - 1] = '\0';

398
input.c
View File

@ -1,4 +1,4 @@
/* $Id: input.c,v 1.43 2007-11-30 11:08:35 nicm Exp $ */ /* $Id: input.c,v 1.44 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -43,7 +43,6 @@ void input_abort_string(struct input_ctx *);
int input_add_string(struct input_ctx *, u_char); int input_add_string(struct input_ctx *, u_char);
char *input_get_string(struct input_ctx *); char *input_get_string(struct input_ctx *);
void input_write(struct input_ctx *, int, ...);
void input_state(struct input_ctx *, void *); void input_state(struct input_ctx *, void *);
void input_state_first(u_char, struct input_ctx *); void input_state_first(u_char, struct input_ctx *);
@ -85,13 +84,6 @@ void input_handle_sequence_decstbm(struct input_ctx *);
void input_handle_sequence_sgr(struct input_ctx *); void input_handle_sequence_sgr(struct input_ctx *);
void input_handle_sequence_dsr(struct input_ctx *); void input_handle_sequence_dsr(struct input_ctx *);
#define input_limit(v, lower, upper) do { \
if (v < lower) \
v = lower; \
if (v > upper) \
v = upper; \
} while (0)
int int
input_new_argument(struct input_ctx *ictx) input_new_argument(struct input_ctx *ictx)
{ {
@ -183,19 +175,6 @@ input_get_string(struct input_ctx *ictx)
return (s); return (s);
} }
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_state(struct input_ctx *ictx, void *state) input_state(struct input_ctx *ictx, void *state)
{ {
@ -239,11 +218,18 @@ input_parse(struct window *w)
log_debug2("entry; buffer=%zu", ictx->len); log_debug2("entry; buffer=%zu", ictx->len);
if (w->mode == NULL)
screen_write_start(&ictx->ctx, &w->base, tty_write_window, w);
else
screen_write_start(&ictx->ctx, &w->base, NULL, NULL);
while (ictx->off < ictx->len) { while (ictx->off < ictx->len) {
ch = ictx->buf[ictx->off++]; ch = ictx->buf[ictx->off++];
ictx->state(ch, ictx); ictx->state(ch, ictx);
} }
screen_write_stop(&ictx->ctx);
buffer_remove(w->in, ictx->len); buffer_remove(w->in, ictx->len);
} }
@ -253,7 +239,7 @@ input_state_first(u_char ch, struct input_ctx *ictx)
if (INPUT_C0CONTROL(ch)) { if (INPUT_C0CONTROL(ch)) {
if (ch == 0x1b) if (ch == 0x1b)
input_state(ictx, input_state_escape); input_state(ictx, input_state_escape);
else else
input_handle_c0_control(ch, ictx); input_handle_c0_control(ch, ictx);
return; return;
} }
@ -268,10 +254,10 @@ input_state_first(u_char ch, struct input_ctx *ictx)
input_handle_c1_control(ch, ictx); input_handle_c1_control(ch, ictx);
return; return;
} }
input_handle_character(ch, ictx); input_handle_character(ch, ictx);
} }
void void
input_state_escape(u_char ch, struct input_ctx *ictx) input_state_escape(u_char ch, struct input_ctx *ictx)
{ {
@ -326,7 +312,7 @@ input_state_title_first(u_char ch, struct input_ctx *ictx)
input_start_string(ictx, STRING_IGNORE); input_start_string(ictx, STRING_IGNORE);
input_state(ictx, input_state_title_second); input_state(ictx, input_state_title_second);
return; return;
} }
input_state(ictx, input_state_first); input_state(ictx, input_state_first);
} }
@ -345,13 +331,10 @@ input_state_title_second(u_char ch, struct input_ctx *ictx)
void void
input_state_title_next(u_char ch, struct input_ctx *ictx) input_state_title_next(u_char ch, struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen;
if (ch == '\007') { if (ch == '\007') {
if (ictx->string_type == STRING_TITLE) { if (ictx->string_type == STRING_TITLE) {
xfree(s->title); screen_write_set_title(
s->title = input_get_string(ictx); &ictx->ctx, input_get_string(ictx));
input_write(ictx, TTY_TITLE, s->title);
} else } else
input_abort_string(ictx); input_abort_string(ictx);
input_state(ictx, input_state_first); input_state(ictx, input_state_first);
@ -440,7 +423,7 @@ input_state_sequence_next(u_char ch, struct input_ctx *ictx)
} }
return; return;
} }
input_state(ictx, input_state_first); input_state(ictx, input_state_first);
} }
@ -449,13 +432,13 @@ input_state_sequence_intermediate(u_char ch, struct input_ctx *ictx)
{ {
if (INPUT_INTERMEDIATE(ch)) if (INPUT_INTERMEDIATE(ch))
return; return;
if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) { if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
input_state(ictx, input_state_first); input_state(ictx, input_state_first);
input_handle_sequence(ch, ictx); input_handle_sequence(ch, ictx);
return; return;
} }
input_state(ictx, input_state_first); input_state(ictx, input_state_first);
} }
@ -496,82 +479,63 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
void void
input_handle_character(u_char ch, struct input_ctx *ictx) input_handle_character(u_char ch, struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen;
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)) {
input_write(ictx, TTY_CHARACTER, '\r');
input_write(ictx, TTY_CHARACTER, '\n');
s->cx = 0; screen_write_put_character(&ictx->ctx, ch);
screen_display_cursor_down(s);
} else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy))
return;
screen_display_cursor_set(s, ch);
input_write(ictx, TTY_CHARACTER, ch);
s->cx++;
} }
void void
input_handle_c0_control(u_char ch, struct input_ctx *ictx) input_handle_c0_control(u_char ch, struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
log_debug2("-- c0 %zu: %hhu", ictx->off, ch); log_debug2("-- c0 %zu: %hhu", ictx->off, ch);
switch (ch) { switch (ch) {
case '\0': /* NUL */ case '\0': /* NUL */
return; break;
case '\n': /* LF */ case '\n': /* LF */
screen_display_cursor_down(s); screen_write_cursor_down_scroll(&ictx->ctx);
break; break;
case '\r': /* CR */ case '\r': /* CR */
s->cx = 0; screen_write_move_cursor(&ictx->ctx, 0, s->cy);
break; break;
case '\007': /* BELL */ case '\007': /* BELL */
ictx->w->flags |= WINDOW_BELL; ictx->w->flags |= WINDOW_BELL;
return; break;
case '\010': /* BS */ case '\010': /* BS */
if (s->cx > 0) screen_write_cursor_left(&ictx->ctx, 1);
s->cx--;
break; break;
case '\011': /* TAB */ case '\011': /* TAB */
s->cx = ((s->cx / 8) * 8) + 8; s->cx = ((s->cx / 8) * 8) + 8;
if (s->cx > screen_last_x(s)) { if (s->cx > screen_last_x(s)) {
s->cx = 0; s->cx = 0;
screen_display_cursor_down(s); screen_write_cursor_down(&ictx->ctx, 1);
} }
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); screen_write_move_cursor(&ictx->ctx, s->cx, s->cy);
return; break;
case '\016': /* SO */ case '\016': /* SO */
s->attr |= ATTR_CHARSET; s->attr |= ATTR_CHARSET;
input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); screen_write_set_attributes(&ictx->ctx, s->attr, s->colr);
return; break;
case '\017': /* SI */ case '\017': /* SI */
s->attr &= ~ATTR_CHARSET; s->attr &= ~ATTR_CHARSET;
input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); screen_write_set_attributes(&ictx->ctx, s->attr, s->colr);
return; break;
default: default:
log_debug("unknown c0: %hhu", ch); log_debug("unknown c0: %hhu", ch);
return; break;
} }
input_write(ictx, TTY_CHARACTER, ch);
} }
void void
input_handle_c1_control(u_char ch, struct input_ctx *ictx) input_handle_c1_control(u_char ch, struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen;
log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch); log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch);
switch (ch) { switch (ch) {
case 'M': /* RI */ case 'M': /* RI */
screen_display_cursor_up(s); screen_write_cursor_up_scroll(&ictx->ctx);
input_write(ictx, TTY_REVERSEINDEX);
break; break;
default: default:
log_debug("unknown c1: %hhu", ch); log_debug("unknown c1: %hhu", ch);
@ -582,16 +546,16 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx)
void void
input_handle_private_two(u_char ch, struct input_ctx *ictx) input_handle_private_two(u_char ch, struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
log_debug2("-- p2 %zu: %hhu (%c)", ictx->off, ch, ch); log_debug2("-- p2 %zu: %hhu (%c)", ictx->off, ch, ch);
switch (ch) { switch (ch) {
case '=': /* DECKPAM */ case '=': /* DECKPAM */
input_write(ictx, TTY_KKEYPADON); screen_write_set_mode(&ictx->ctx, MODE_KKEYPAD);
break; break;
case '>': /* DECKPNM*/ case '>': /* DECKPNM*/
input_write(ictx, TTY_KKEYPADOFF); screen_write_clear_mode(&ictx->ctx, MODE_KKEYPAD);
break; break;
case '7': /* DECSC */ case '7': /* DECSC */
s->saved_cx = s->cx; s->saved_cx = s->cx;
@ -607,8 +571,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;
input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); screen_write_set_attributes(&ictx->ctx, s->attr, s->colr);
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); screen_write_move_cursor(&ictx->ctx, s->cx, s->cy);
break; break;
default: default:
log_debug("unknown p2: %hhu", ch); log_debug("unknown p2: %hhu", ch);
@ -659,10 +623,10 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx)
{ 'n', input_handle_sequence_dsr }, { 'n', input_handle_sequence_dsr },
{ 'r', input_handle_sequence_decstbm }, { 'r', input_handle_sequence_decstbm },
}; };
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
u_int i; u_int i;
struct input_arg *iarg; struct input_arg *iarg;
log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, " log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, "
"ru=%u, rl=%u]", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args), "ru=%u, rl=%u]", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args),
screen_size_x(s), screen_size_y(s), s->cx, s->cy, s->rupper, screen_size_x(s), screen_size_y(s), s->cx, s->cy, s->rupper,
@ -687,8 +651,7 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx)
void void
input_handle_sequence_cuu(struct input_ctx *ictx) input_handle_sequence_cuu(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -697,21 +660,16 @@ input_handle_sequence_cuu(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0)
n = 1;
if (n == 0 || n > s->cy) { screen_write_cursor_up(&ictx->ctx, n);
log_debug3("cuu: out of range: %hu", n);
return;
}
s->cy -= n;
input_write(ictx, TTY_CURSORUP, n);
} }
void void
input_handle_sequence_cud(struct input_ctx *ictx) input_handle_sequence_cud(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -720,20 +678,16 @@ input_handle_sequence_cud(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_y(s) - s->cy);
s->cy += n; screen_write_cursor_down(&ictx->ctx, n);
input_write(ictx, TTY_CURSORDOWN, n);
} }
void void
input_handle_sequence_cuf(struct input_ctx *ictx) input_handle_sequence_cuf(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -742,20 +696,16 @@ input_handle_sequence_cuf(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_x(s) - s->cx);
s->cx += n; screen_write_cursor_right(&ictx->ctx, n);
input_write(ictx, TTY_CURSORRIGHT, n);
} }
void void
input_handle_sequence_cub(struct input_ctx *ictx) input_handle_sequence_cub(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -764,21 +714,16 @@ input_handle_sequence_cub(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0)
n = 1;
if (n == 0 || n > s->cx) { screen_write_cursor_left(&ictx->ctx, n);
log_debug3("cub: out of range: %hu", n);
return;
}
s->cx -= n;
input_write(ictx, TTY_CURSORLEFT, n);
} }
void void
input_handle_sequence_dch(struct input_ctx *ictx) input_handle_sequence_dch(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -787,20 +732,16 @@ input_handle_sequence_dch(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_x(s) - s->cx);
screen_display_delete_characters(s, s->cx, s->cy, n); screen_write_delete_characters(&ictx->ctx, n);
input_write(ictx, TTY_DELETECHARACTER, n);
} }
void void
input_handle_sequence_dl(struct input_ctx *ictx) input_handle_sequence_dl(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -809,23 +750,16 @@ input_handle_sequence_dl(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_y(s) - s->cy);
if (s->cy < s->rupper || s->cy > s->rlower) screen_write_delete_lines(&ictx->ctx, n);
screen_display_delete_lines(s, s->cy, n);
else
screen_display_delete_lines_region(s, s->cy, n);
input_write(ictx, TTY_DELETELINE, n);
} }
void void
input_handle_sequence_ich(struct input_ctx *ictx) input_handle_sequence_ich(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -834,20 +768,16 @@ input_handle_sequence_ich(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_x(s) - s->cx);
screen_display_insert_characters(s, s->cx, s->cy, n); screen_write_insert_characters(&ictx->ctx, n);
input_write(ictx, TTY_INSERTCHARACTER, n);
} }
void void
input_handle_sequence_il(struct input_ctx *ictx) input_handle_sequence_il(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -856,23 +786,17 @@ input_handle_sequence_il(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_last_y(s) - s->cy);
if (s->cy < s->rupper || s->cy > s->rlower) screen_write_insert_lines(&ictx->ctx, n);
screen_display_insert_lines(s, s->cy, n);
else
screen_display_insert_lines_region(s, s->cy, n);
input_write(ictx, TTY_INSERTLINE, n);
} }
void void
input_handle_sequence_vpa(struct input_ctx *ictx) input_handle_sequence_vpa(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
uint16_t n; uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -881,20 +805,17 @@ input_handle_sequence_vpa(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_size_y(s));
s->cy = n - 1; screen_write_move_cursor(&ictx->ctx, s->cx, n - 1);
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
} }
void void
input_handle_sequence_hpa(struct input_ctx *ictx) input_handle_sequence_hpa(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
uint16_t n; uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -903,20 +824,16 @@ input_handle_sequence_hpa(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 1) != 0) if (input_get_argument(ictx, 0, &n, 1) != 0)
return; return;
if (n == 0) if (n == 0)
return; n = 1;
input_limit(n, 1, screen_size_x(s));
s->cx = n - 1; screen_write_move_cursor(&ictx->ctx, n - 1, s->cy);
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
} }
void void
input_handle_sequence_cup(struct input_ctx *ictx) input_handle_sequence_cup(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n, m;
uint16_t n, m;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -927,21 +844,18 @@ input_handle_sequence_cup(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 1, &m, 1) != 0) if (input_get_argument(ictx, 1, &m, 1) != 0)
return; return;
if (n == 0)
n = 1;
if (m == 0)
m = 1;
input_limit(n, 1, screen_size_y(s)); screen_write_move_cursor(&ictx->ctx, m - 1, n - 1);
input_limit(m, 1, screen_size_x(s));
s->cx = m - 1;
s->cy = n - 1;
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
} }
void void
input_handle_sequence_ed(struct input_ctx *ictx) input_handle_sequence_ed(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
u_int i;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -950,31 +864,15 @@ input_handle_sequence_ed(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 0) != 0) if (input_get_argument(ictx, 0, &n, 0) != 0)
return; return;
if (n > 2) if (n > 2)
return; return;
switch (n) { switch (n) {
case 0: case 0:
screen_display_fill_cursor_eos( screen_write_fill_end_of_screen(&ictx->ctx);
s, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARENDOFLINE);
for (i = s->cy + 1; i < screen_size_y(s); i++) {
input_write(ictx, TTY_CURSORMOVE, i, 0);
input_write(ictx, TTY_CLEARENDOFLINE);
}
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
break; break;
case 2: case 2:
screen_display_fill_lines( screen_write_fill_screen(&ictx->ctx);
s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr);
for (i = 0; i < screen_size_y(s); i++) {
input_write(ictx, TTY_CURSORMOVE, i, 0);
input_write(ictx, TTY_CLEARENDOFLINE);
}
input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx);
break; break;
} }
} }
@ -982,8 +880,7 @@ input_handle_sequence_ed(struct input_ctx *ictx)
void void
input_handle_sequence_el(struct input_ctx *ictx) input_handle_sequence_el(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -992,25 +889,18 @@ input_handle_sequence_el(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 0, &n, 0) != 0) if (input_get_argument(ictx, 0, &n, 0) != 0)
return; return;
if (n > 2) if (n > 2)
return; return;
switch (n) { switch (n) {
case 0: case 0:
screen_display_fill_cursor_eol( screen_write_fill_end_of_line(&ictx->ctx);
s, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARENDOFLINE);
break; break;
case 1: case 1:
screen_display_fill_cursor_bol( screen_write_fill_start_of_line(&ictx->ctx);
s, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARSTARTOFLINE);
break; break;
case 2: case 2:
screen_display_fill_line( screen_write_fill_line(&ictx->ctx);
s, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
input_write(ictx, TTY_CLEARLINE);
break; break;
} }
} }
@ -1018,8 +908,7 @@ input_handle_sequence_el(struct input_ctx *ictx)
void void
input_handle_sequence_sm(struct input_ctx *ictx) input_handle_sequence_sm(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; uint16_t n;
uint16_t n;
if (ARRAY_LENGTH(&ictx->args) > 1) if (ARRAY_LENGTH(&ictx->args) > 1)
return; return;
@ -1029,16 +918,13 @@ input_handle_sequence_sm(struct input_ctx *ictx)
if (ictx->private == '?') { if (ictx->private == '?') {
switch (n) { switch (n) {
case 1: /* GATM */ case 1: /* GATM */
s->mode |= MODE_KCURSOR; screen_write_set_mode(&ictx->ctx, MODE_KCURSOR);
input_write(ictx, TTY_KCURSORON);
break; break;
case 25: /* TCEM */ case 25: /* TCEM */
s->mode |= MODE_CURSOR; screen_write_set_mode(&ictx->ctx, MODE_CURSOR);
input_write(ictx, TTY_CURSORON);
break; break;
case 1000: case 1000:
s->mode |= MODE_MOUSE; screen_write_set_mode(&ictx->ctx, MODE_MOUSE);
input_write(ictx, TTY_MOUSEON);
break; break;
default: default:
log_debug("unknown SM [%hhu]: %u", ictx->private, n); log_debug("unknown SM [%hhu]: %u", ictx->private, n);
@ -1047,8 +933,7 @@ input_handle_sequence_sm(struct input_ctx *ictx)
} else { } else {
switch (n) { switch (n) {
case 4: /* IRM */ case 4: /* IRM */
s->mode |= MODE_INSERT; screen_write_set_mode(&ictx->ctx, MODE_INSERT);
input_write(ictx, TTY_INSERTON);
break; break;
case 34: case 34:
/* Cursor high visibility not supported. */ /* Cursor high visibility not supported. */
@ -1063,7 +948,6 @@ input_handle_sequence_sm(struct input_ctx *ictx)
void void
input_handle_sequence_rm(struct input_ctx *ictx) input_handle_sequence_rm(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen;
uint16_t n; uint16_t n;
if (ARRAY_LENGTH(&ictx->args) > 1) if (ARRAY_LENGTH(&ictx->args) > 1)
@ -1074,16 +958,13 @@ input_handle_sequence_rm(struct input_ctx *ictx)
if (ictx->private == '?') { if (ictx->private == '?') {
switch (n) { switch (n) {
case 1: /* GATM */ case 1: /* GATM */
s->mode &= ~MODE_KCURSOR; screen_write_clear_mode(&ictx->ctx, MODE_KCURSOR);
input_write(ictx, TTY_KCURSOROFF);
break; break;
case 25: /* TCEM */ case 25: /* TCEM */
s->mode &= ~MODE_CURSOR; screen_write_clear_mode(&ictx->ctx, MODE_CURSOR);
input_write(ictx, TTY_CURSOROFF);
break; break;
case 1000: case 1000:
s->mode &= ~MODE_MOUSE; screen_write_clear_mode(&ictx->ctx, MODE_MOUSE);
input_write(ictx, TTY_MOUSEOFF);
break; break;
default: default:
log_debug("unknown RM [%hhu]: %u", ictx->private, n); log_debug("unknown RM [%hhu]: %u", ictx->private, n);
@ -1092,8 +973,7 @@ input_handle_sequence_rm(struct input_ctx *ictx)
} else if (ictx->private == '\0') { } else if (ictx->private == '\0') {
switch (n) { switch (n) {
case 4: /* IRM */ case 4: /* IRM */
s->mode &= ~MODE_INSERT; screen_write_clear_mode(&ictx->ctx, MODE_INSERT);
input_write(ictx, TTY_INSERTOFF);
break; break;
case 34: case 34:
/* Cursor high visibility not supported. */ /* Cursor high visibility not supported. */
@ -1108,9 +988,9 @@ input_handle_sequence_rm(struct input_ctx *ictx)
void void
input_handle_sequence_dsr(struct input_ctx *ictx) input_handle_sequence_dsr(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
uint16_t n; uint16_t n;
char reply[32]; char reply[32];
if (ARRAY_LENGTH(&ictx->args) > 1) if (ARRAY_LENGTH(&ictx->args) > 1)
return; return;
@ -1133,8 +1013,8 @@ input_handle_sequence_dsr(struct input_ctx *ictx)
void void
input_handle_sequence_decstbm(struct input_ctx *ictx) input_handle_sequence_decstbm(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
uint16_t n, m; uint16_t n, m;
if (ictx->private != '\0') if (ictx->private != '\0')
return; return;
@ -1145,78 +1025,64 @@ input_handle_sequence_decstbm(struct input_ctx *ictx)
return; return;
if (input_get_argument(ictx, 1, &m, 0) != 0) if (input_get_argument(ictx, 1, &m, 0) != 0)
return; return;
if (n == 0)
/* Special case: both zero restores to entire screen. */
/* XXX this will catch [0;0r and [;r etc too, is this right? */
if (n == 0 && m == 0) {
n = 1; n = 1;
if (m == 0)
m = screen_size_y(s); m = screen_size_y(s);
}
input_limit(n, 1, screen_size_y(s)); screen_write_set_region(&ictx->ctx, n - 1, m - 1);
input_limit(m, 1, screen_size_y(s));
if (n > m) {
log_debug3("decstbm: out of range: %hu,%hu", n, m);
return;
}
/* Cursor moves to top-left. */
s->cx = 0;
s->cy = n - 1;
s->rupper = n - 1;
s->rlower = m - 1;
input_write(ictx, TTY_SCROLLREGION, s->rupper, s->rlower);
} }
void void
input_handle_sequence_sgr(struct input_ctx *ictx) input_handle_sequence_sgr(struct input_ctx *ictx)
{ {
struct screen *s = &ictx->w->screen; struct screen *s = ictx->ctx.s;
u_int i, n; u_int i, n;
uint16_t m; uint16_t m;
u_char attr, colr;
n = ARRAY_LENGTH(&ictx->args); n = ARRAY_LENGTH(&ictx->args);
if (n == 0) { if (n == 0) {
s->attr = 0; attr = 0;
s->colr = SCREEN_DEFCOLR; colr = SCREEN_DEFCOLR;
} else { } else {
attr = s->attr;
colr = s->colr;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (input_get_argument(ictx, i, &m, 0) != 0) if (input_get_argument(ictx, i, &m, 0) != 0)
return; return;
switch (m) { switch (m) {
case 0: case 0:
case 10: case 10:
s->attr &= ATTR_CHARSET; attr &= ATTR_CHARSET;
s->colr = SCREEN_DEFCOLR; colr = SCREEN_DEFCOLR;
break; break;
case 1: case 1:
s->attr |= ATTR_BRIGHT; attr |= ATTR_BRIGHT;
break; break;
case 2: case 2:
s->attr |= ATTR_DIM; attr |= ATTR_DIM;
break; break;
case 3: case 3:
s->attr |= ATTR_ITALICS; attr |= ATTR_ITALICS;
break; break;
case 4: case 4:
s->attr |= ATTR_UNDERSCORE; attr |= ATTR_UNDERSCORE;
break; break;
case 5: case 5:
s->attr |= ATTR_BLINK; attr |= ATTR_BLINK;
break; break;
case 7: case 7:
s->attr |= ATTR_REVERSE; attr |= ATTR_REVERSE;
break; break;
case 8: case 8:
s->attr |= ATTR_HIDDEN; attr |= ATTR_HIDDEN;
break; break;
case 23: case 23:
s->attr &= ~ATTR_ITALICS; attr &= ~ATTR_ITALICS;
break; break;
case 24: case 24:
s->attr &= ~ATTR_UNDERSCORE; attr &= ~ATTR_UNDERSCORE;
break; break;
case 30: case 30:
case 31: case 31:
@ -1226,12 +1092,12 @@ input_handle_sequence_sgr(struct input_ctx *ictx)
case 35: case 35:
case 36: case 36:
case 37: case 37:
s->colr &= 0x0f; colr &= 0x0f;
s->colr |= (m - 30) << 4; colr |= (m - 30) << 4;
break; break;
case 39: case 39:
s->colr &= 0x0f; colr &= 0x0f;
s->colr |= 0x80; colr |= 0x80;
break; break;
case 40: case 40:
case 41: case 41:
@ -1241,15 +1107,15 @@ input_handle_sequence_sgr(struct input_ctx *ictx)
case 45: case 45:
case 46: case 46:
case 47: case 47:
s->colr &= 0xf0; colr &= 0xf0;
s->colr |= m - 40; colr |= m - 40;
break; break;
case 49: case 49:
s->colr &= 0xf0; colr &= 0xf0;
s->colr |= 0x08; colr |= 0x08;
break; break;
} }
} }
} }
input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); screen_write_set_attributes(&ictx->ctx, attr, colr);
} }

View File

@ -1,4 +1,4 @@
/* $Id: key-bindings.c,v 1.22 2007-11-27 19:23:33 nicm Exp $ */ /* $Id: key-bindings.c,v 1.23 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -84,7 +84,7 @@ key_bindings_init(void)
{ 'S', &cmd_list_sessions_entry, NULL }, { 'S', &cmd_list_sessions_entry, NULL },
{ 's', &cmd_list_sessions_entry, NULL }, { 's', &cmd_list_sessions_entry, NULL },
{ 'W', &cmd_list_windows_entry, NULL }, { 'W', &cmd_list_windows_entry, NULL },
{ 'w', &cmd_list_windows_entry, NULL }, { 'w', &cmd_list_windows_entry, NULL },
{ '?', &cmd_list_keys_entry, NULL }, { '?', &cmd_list_keys_entry, NULL },
{ '/', &cmd_list_keys_entry, NULL }, { '/', &cmd_list_keys_entry, NULL },
{ 'C', &cmd_new_window_entry, NULL }, { 'C', &cmd_new_window_entry, NULL },
@ -140,7 +140,7 @@ key_bindings_free(void)
cmd_free(bd->cmd); cmd_free(bd->cmd);
xfree(bd); xfree(bd);
} }
ARRAY_FREE(&key_bindings); ARRAY_FREE(&key_bindings);
} }
@ -168,6 +168,7 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
if (w->mode == NULL) { if (w->mode == NULL) {
w->mode = &window_more_mode; w->mode = &window_more_mode;
w->mode->init(w); w->mode->init(w);
server_redraw_window(w);
} else if (w->mode != &window_more_mode) } else if (w->mode != &window_more_mode)
return; return;
@ -202,7 +203,4 @@ key_bindings_dispatch(int key, struct client *c)
ctx.flags = CMD_KEY; ctx.flags = CMD_KEY;
cmd_exec(bd->cmd, &ctx); cmd_exec(bd->cmd, &ctx);
if (c->session->curw->window->mode == &window_more_mode)
server_redraw_window(c->session->curw->window);
} }

View File

@ -1,4 +1,4 @@
/* $Id: resize.c,v 1.8 2007-12-02 23:00:22 nicm Exp $ */ /* $Id: resize.c,v 1.9 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,7 +33,7 @@
* smallest client it is attached to, and resize it to that size. Then for * smallest client it is attached to, and resize it to that size. Then for
* every window, find the smallest session it is attached to, resize it to that * every window, find the smallest session it is attached to, resize it to that
* size and clear and redraw every client with it as the current window. * size and clear and redraw every client with it as the current window.
* *
* This is quite inefficient - better/additional data structures are needed * This is quite inefficient - better/additional data structures are needed
* to make it better. * to make it better.
* *
@ -50,7 +50,7 @@ recalculate_sizes(void)
struct client *c; struct client *c;
struct window *w; struct window *w;
u_int i, j, ssx, ssy; u_int i, j, ssx, ssy;
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) if (s == NULL)
@ -105,17 +105,17 @@ recalculate_sizes(void)
} }
} }
if (ssx == UINT_MAX || ssy == UINT_MAX) { if (ssx == UINT_MAX || ssy == UINT_MAX) {
w->screen.mode |= MODE_HIDDEN; w->flags |= WINDOW_HIDDEN;
continue; continue;
} }
w->screen.mode &= ~MODE_HIDDEN; w->flags &= ~WINDOW_HIDDEN;
if (screen_size_x(&w->screen) == ssx && if (screen_size_x(&w->base) == ssx &&
screen_size_y(&w->screen) == ssy) screen_size_y(&w->base) == ssy)
continue; continue;
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->base), screen_size_y(&w->base));
server_clear_window(w); server_clear_window(w);
window_resize(w, ssx, ssy); window_resize(w, ssx, ssy);

View File

@ -1,4 +1,4 @@
/* $Id: screen-display.c,v 1.9 2007-11-26 22:22:18 nicm Exp $ */ /* $Id: screen-display.c,v 1.10 2007-12-06 09:46:22 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -22,17 +22,20 @@
#include "tmux.h" #include "tmux.h"
/* /* Set a cell. */
* Screen display modification functions. These alter the displayed portion void
* of the screen. screen_display_set_cell(
*/ struct screen *s, u_int px, u_int py, u_char data, u_char attr, u_char colr)
{
screen_set_cell(s, screen_x(s, px), screen_y(s, py), data, attr, colr);
}
/* Create a region of lines. */ /* Create a region of lines. */
void void
screen_display_make_lines(struct screen *s, u_int py, u_int ny) screen_display_make_lines(struct screen *s, u_int py, u_int ny)
{ {
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1))
fatalx("bad value"); return;
screen_make_lines(s, screen_y(s, py), ny); screen_make_lines(s, screen_y(s, py), ny);
} }
@ -41,7 +44,7 @@ void
screen_display_free_lines(struct screen *s, u_int py, u_int ny) screen_display_free_lines(struct screen *s, u_int py, u_int ny)
{ {
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1))
fatalx("bad value"); return;
screen_free_lines(s, screen_y(s, py), ny); screen_free_lines(s, screen_y(s, py), ny);
} }
@ -50,116 +53,25 @@ void
screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny)
{ {
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1))
fatalx("bad value"); return;
if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py)
fatalx("bad value"); return;
screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny); screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny);
} }
/* Fill a set of lines. */ /* Fill a set of cells. */
void void
screen_display_fill_lines( screen_display_fill_area(struct screen *s, u_int px, u_int py,
struct screen *s, u_int py, u_int ny, u_char data, u_char attr, u_char colr) u_int nx, u_int ny, u_char data, u_char attr, u_char colr)
{ {
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) if (nx == 0 || ny == 0)
fatalx("bad value"); return;
screen_fill_lines(s, screen_y(s, py), ny, data, attr, colr); if (!screen_in_x(s, px) || !screen_in_y(s, py))
} return;
if (!screen_in_x(s, px + nx - 1) || !screen_in_y(s, py - ny - 1))
/* Fill a set of cellss. */ return;
void screen_fill_area(
screen_display_fill_cells(struct screen *s, s, screen_x(s, px), screen_y(s, py), nx, ny, data, attr, colr);
u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr)
{
if (nx == 0 || !screen_in_x(s, px) || !screen_in_y(s, py))
fatalx("bad value");
screen_fill_cells(
s, screen_x(s, px), screen_y(s, py), nx, data, attr, colr);
}
/* Fill entire screen. */
void
screen_display_fill_screen(
struct screen *s, u_char data, u_char attr, u_char colr)
{
screen_display_fill_lines(s, 0, screen_size_y(s), data, attr, colr);
}
/* Fill end of screen from cursor. */
void
screen_display_fill_cursor_eos(
struct screen *s, u_char data, u_char attr, u_char colr)
{
screen_display_fill_cursor_eol(s, data, attr, colr);
if (s->cy != screen_last_y(s)) {
screen_display_fill_lines(
s, s->cy, screen_size_y(s) - s->cy, data, attr, colr);
}
}
/* Fill beginning of screen from cursor. */
void
screen_display_fill_cursor_bos(
struct screen *s, u_char data, u_char attr, u_char colr)
{
screen_display_fill_lines(s, 0, s->cy, data, attr, colr);
}
/* Fill a single line. */
void
screen_display_fill_line(
struct screen *s, u_int py, u_char data, u_char attr, u_char colr)
{
screen_display_fill_lines(s, py, 1, data, attr, colr);
}
/* Fill cursor to beginning of line. */
void
screen_display_fill_cursor_bol(
struct screen *s, u_char data, u_char attr, u_char colr)
{
screen_display_fill_cells(s, 0, s->cy, s->cx, data, attr, colr);
}
/* Fill cursor to end of line. */
void
screen_display_fill_cursor_eol(
struct screen *s, u_char data, u_char attr, u_char colr)
{
screen_display_fill_cells(
s, s->cx, s->cy, screen_size_x(s) - s->cx, data, attr, colr);
}
/* Set character at cursor. */
void
screen_display_cursor_set(struct screen *s, u_char ch)
{
u_int px, py;
px = screen_x(s, s->cx);
py = screen_y(s, s->cy);
screen_set_cell(s, px, py, ch, s->attr, s->colr);
}
/* Move cursor up and scroll if necessary. */
void
screen_display_cursor_up(struct screen *s)
{
if (s->cy == s->rupper)
screen_display_scroll_region_down(s);
else if (s->cy > 0)
s->cy--;
}
/* Move cursor down and scroll if necessary. */
void
screen_display_cursor_down(struct screen *s)
{
if (s->cy == s->rlower)
screen_display_scroll_region_up(s);
else if (s->cy < screen_last_y(s))
s->cy++;
} }
/* Scroll region up. */ /* Scroll region up. */
@ -167,13 +79,13 @@ void
screen_display_scroll_region_up(struct screen *s) screen_display_scroll_region_up(struct screen *s)
{ {
u_int ny, sy; u_int ny, sy;
/* /*
* If the region is the entire screen, this is easy-peasy. Allocate * If the region is the entire screen, this is easy-peasy. Allocate
* a new line and adjust the history size. * a new line and adjust the history size.
* XXX should this be done somewhere else? * XXX should this be done somewhere else?
*/ */
if (s->rupper == 0 && s->rlower == screen_last_y(s)) { if (s->rupper == 0 && s->rlower == screen_last_y(s)) {
if (s->hsize == s->hlimit) { if (s->hsize == s->hlimit) {
/* If the limit is hit, free 10% and shift up. */ /* If the limit is hit, free 10% and shift up. */
ny = s->hlimit / 10; ny = s->hlimit / 10;
@ -197,7 +109,7 @@ screen_display_scroll_region_up(struct screen *s)
return; return;
} }
/* /*
* Scroll scrolling region up: * Scroll scrolling region up:
* - delete rupper * - delete rupper
* - move rupper + 1 to rlower to rupper * - move rupper + 1 to rlower to rupper
@ -213,7 +125,7 @@ screen_display_scroll_region_up(struct screen *s)
screen_display_free_lines(s, s->rupper, 1); screen_display_free_lines(s, s->rupper, 1);
if (s->rupper != s->rlower) { if (s->rupper != s->rlower) {
screen_display_move_lines(s, screen_display_move_lines(s,
s->rupper, s->rupper + 1, s->rlower - s->rupper); s->rupper, s->rupper + 1, s->rlower - s->rupper);
} }
@ -224,7 +136,7 @@ screen_display_scroll_region_up(struct screen *s)
void void
screen_display_scroll_region_down(struct screen *s) screen_display_scroll_region_down(struct screen *s)
{ {
/* /*
* Scroll scrolling region down: * Scroll scrolling region down:
* - delete rlower * - delete rlower
* - move rupper to rlower - 1 to rupper + 1 * - move rupper to rlower - 1 to rupper + 1
@ -252,14 +164,14 @@ void
screen_display_insert_lines(struct screen *s, u_int py, u_int ny) screen_display_insert_lines(struct screen *s, u_int py, u_int ny)
{ {
if (!screen_in_y(s, py)) if (!screen_in_y(s, py))
fatalx("bad value"); return;
if (ny == 0) if (ny == 0)
fatalx("bad value"); return;
if (py + ny > screen_last_y(s)) if (py + ny > screen_last_y(s))
ny = screen_size_y(s) - py; ny = screen_size_y(s) - py;
if (ny == 0) if (ny == 0)
return; return;
/* /*
* Insert range of ny lines at py: * Insert range of ny lines at py:
@ -289,9 +201,9 @@ void
screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny) screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny)
{ {
if (!screen_in_region(s, py)) if (!screen_in_region(s, py))
fatalx("bad value"); return;
if (ny == 0) if (ny == 0)
fatalx("bad value"); return;
if (py + ny > s->rlower) if (py + ny > s->rlower)
ny = (s->rlower + 1) - py; ny = (s->rlower + 1) - py;
@ -326,9 +238,9 @@ void
screen_display_delete_lines(struct screen *s, u_int py, u_int ny) screen_display_delete_lines(struct screen *s, u_int py, u_int ny)
{ {
if (!screen_in_y(s, py)) if (!screen_in_y(s, py))
fatalx("bad value"); return;
if (ny == 0) if (ny == 0)
fatalx("bad value"); return;
if (py + ny > screen_last_y(s)) if (py + ny > screen_last_y(s))
ny = screen_size_y(s) - py; ny = screen_size_y(s) - py;
@ -363,9 +275,9 @@ void
screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny) screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny)
{ {
if (!screen_in_region(s, py)) if (!screen_in_region(s, py))
fatalx("bad value"); return;
if (ny == 0) if (ny == 0)
fatalx("bad value"); return;
if (py + ny > s->rlower) if (py + ny > s->rlower)
ny = (s->rlower + 1) - py; ny = (s->rlower + 1) - py;
@ -402,7 +314,7 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx)
u_int mx; u_int mx;
if (!screen_in_x(s, px) || !screen_in_y(s, py)) if (!screen_in_x(s, px) || !screen_in_y(s, py))
fatalx("bad value"); return;
if (px + nx > screen_last_x(s)) if (px + nx > screen_last_x(s))
nx = screen_last_x(s) - px; nx = screen_last_x(s) - px;
@ -439,7 +351,7 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx)
u_int mx; u_int mx;
if (!screen_in_x(s, px) || !screen_in_y(s, py)) if (!screen_in_x(s, px) || !screen_in_y(s, py))
fatalx("bad value"); return;
if (px + nx > screen_last_x(s)) if (px + nx > screen_last_x(s))
nx = screen_last_x(s) - px; nx = screen_last_x(s) - px;
@ -468,3 +380,28 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx)
memset(&s->grid_attr[py][screen_size_x(s) - nx], SCREEN_DEFATTR, nx); memset(&s->grid_attr[py][screen_size_x(s) - nx], SCREEN_DEFATTR, nx);
memset(&s->grid_colr[py][screen_size_x(s) - nx], SCREEN_DEFCOLR, nx); memset(&s->grid_colr[py][screen_size_x(s) - nx], SCREEN_DEFCOLR, nx);
} }
/* Fill cells from another screen, with an offset. */
void
screen_display_copy_area(struct screen *dst, struct screen *src,
u_int px, u_int py, u_int nx, u_int ny, u_int ox, u_int oy)
{
u_int i, j;
u_char data, attr, colr;
if (nx == 0 || ny == 0)
return;
if (!screen_in_x(dst, px) || !screen_in_y(dst, py))
return;
if (!screen_in_x(dst, px + nx - 1) || !screen_in_y(dst, py + ny - 1))
return;
for (i = py; i < py + ny; i++) {
for (j = px; j < px + nx; j++) {
screen_get_cell(src,
screen_x(src, j) + ox, screen_y(src, i) - oy,
&data, &attr, &colr);
screen_display_set_cell(dst, j, i, data, attr, colr);
}
}
}

218
screen-redraw.c Normal file
View File

@ -0,0 +1,218 @@
/* $Id: screen-redraw.c,v 1.1 2007-12-06 09:46:22 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"
void screen_redraw_get_cell(struct screen_redraw_ctx *,
u_int, u_int, u_char *, u_char *, u_char *);
/* Initialise redrawing with a window. */
void
screen_redraw_start_window(struct screen_redraw_ctx *ctx, struct window *w)
{
struct screen *t = w->screen;
screen_redraw_start(ctx, t, tty_write_window, w);
}
/* Initialise redrawing with a client. */
void
screen_redraw_start_client(struct screen_redraw_ctx *ctx, struct client *c)
{
struct screen *t = c->session->curw->window->screen;
screen_redraw_start(ctx, t, tty_write_client, c);
}
/* Initialise redrawing with a session. */
void
screen_redraw_start_session(struct screen_redraw_ctx *ctx, struct session *s)
{
struct screen *t = s->curw->window->screen;
screen_redraw_start(ctx, t, tty_write_session, s);
}
/* Initialise for redrawing. */
void
screen_redraw_start(struct screen_redraw_ctx *ctx,
struct screen *s, void (*write)(void *, int, ...), void *data)
{
ctx->write = write;
ctx->data = data;
ctx->s = s;
/*
* Save screen cursor position. Emulation of some TTY_* commands
* requires this to be correct in the screen, so rather than having
* a local copy and just manipulating it, save the screen's values,
* modify them during redraw, and restore them when finished.
*/
ctx->saved_cx = s->cx;
ctx->saved_cy = s->cy;
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr);
ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s));
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
ctx->write(ctx->data, TTY_CURSOROFF);
ctx->write(ctx->data, TTY_MOUSEOFF);
}
/* Finish redrawing. */
void
screen_redraw_stop(struct screen_redraw_ctx *ctx)
{
struct screen *s = ctx->s;
s->cx = ctx->saved_cx;
s->cy = ctx->saved_cy;
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr);
ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
if (s->mode & MODE_CURSOR)
ctx->write(ctx->data, TTY_CURSORON);
if (s->mode & MODE_MOUSE)
ctx->write(ctx->data, TTY_MOUSEON);
}
/* Get cell data. */
void
screen_redraw_get_cell(struct screen_redraw_ctx *ctx,
u_int px, u_int py, u_char *data, u_char *attr, u_char *colr)
{
struct screen *s = ctx->s;
screen_get_cell(s, screen_x(s, px), screen_y(s, py), data, attr, colr);
}
/* Move cursor. */
void
screen_redraw_move_cursor(struct screen_redraw_ctx *ctx, u_int px, u_int py)
{
if (px != ctx->s->cx || py != ctx->s->cy) {
ctx->s->cx = px;
ctx->s->cy = py;
ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cy, ctx->s->cx);
}
}
/* Set attributes. */
void
screen_redraw_set_attributes(
struct screen_redraw_ctx *ctx, u_int attr, u_int colr)
{
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr);
}
/* Write string. */
void printflike2
screen_redraw_write_string(struct screen_redraw_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->s->cx > screen_last_x(s))
break;
if (*ptr < 0x20)
continue;
ctx->write(ctx->data, TTY_CHARACTER, *ptr);
ctx->s->cx++;
}
xfree(msg);
}
/* Clear screen. */
void
screen_redraw_clear_screen(struct screen_redraw_ctx *ctx)
{
u_int i;
for (i = 0; i < screen_size_y(ctx->s); i++) {
screen_redraw_move_cursor(ctx, 0, i);
ctx->write(ctx->data, TTY_CLEARLINE);
}
}
/* Clear to end of line. */
void
screen_redraw_clear_end_of_line(struct screen_redraw_ctx *ctx)
{
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
/* Redraw single cell. */
void
screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py)
{
u_char data, attr, colr;
screen_redraw_move_cursor(ctx, px, py);
screen_redraw_get_cell(ctx, px, py, &data, &attr, &colr);
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr);
ctx->write(ctx->data, TTY_CHARACTER, data);
ctx->s->cx++;
}
/* Redraw area of cells. */
void
screen_redraw_area(
struct screen_redraw_ctx *ctx, u_int px, u_int py, u_int nx, u_int ny)
{
u_int i, j;
for (i = py; i < py + ny; i++) {
for (j = px; j < px + nx; j++)
screen_redraw_cell(ctx, j, i);
}
}
/* Draw set of lines. */
void
screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny)
{
u_int i, cx, sx;
sx = screen_size_x(ctx->s);
for (i = py; i < py + ny; i++) {
cx = ctx->s->grid_size[screen_y(ctx->s, i)];
if (ctx->s->sel.flag || sx < 5 || cx >= sx - 5) {
screen_redraw_area(ctx, 0, i, screen_size_x(ctx->s), 1);
continue;
}
screen_redraw_area(ctx, 0, i, cx, 1);
screen_redraw_move_cursor(ctx, cx, i);
screen_redraw_set_attributes(
ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
}

516
screen-write.c Normal file
View File

@ -0,0 +1,516 @@
/* $Id: screen-write.c,v 1.1 2007-12-06 09:46:23 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"
#define screen_write_limit(v, lower, upper) do { \
if (v < lower) \
v = lower; \
if (v > upper) \
v = upper; \
} while (0)
/* Initialise writing with a window. */
void
screen_write_start_window(struct screen_write_ctx *ctx, struct window *w)
{
struct screen *t = w->screen;
screen_write_start(ctx, t, tty_write_window, w);
}
/* Initialise writing with a client. */
void
screen_write_start_client(struct screen_write_ctx *ctx, struct client *c)
{
struct screen *t = c->session->curw->window->screen;
screen_write_start(ctx, t, tty_write_client, c);
}
/* Initialise writing with a session. */
void
screen_write_start_session(struct screen_write_ctx *ctx, struct session *s)
{
struct screen *t = s->curw->window->screen;
screen_write_start(ctx, t, tty_write_session, s);
}
/* Initialise writing. */
void
screen_write_start(struct screen_write_ctx *ctx,
struct screen *s, void (*write)(void *, int, ...), void *data)
{
ctx->write = write;
ctx->data = data;
ctx->s = s;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSOROFF);
}
/* Finalise writing. */
void
screen_write_stop(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
if (ctx->write != NULL && s->mode & MODE_CURSOR)
ctx->write(ctx->data, TTY_CURSORON);
}
/* Set screen title. */
void
screen_write_set_title(struct screen_write_ctx *ctx, char *title)
{
struct screen *s = ctx->s;
xfree(s->title);
s->title = title;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_TITLE, s->title);
}
/* Put a character. */
void
screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
{
struct screen *s = ctx->s;
if (s->cx == screen_size_x(s)) {
s->cx = 0;
screen_write_cursor_down_scroll(ctx);
} else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy))
return;
screen_display_set_cell(s, s->cx, s->cy, ch, s->attr, s->colr);
s->cx++;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CHARACTER, ch);
}
/* Put a string right-justified. */
size_t printflike2
screen_write_put_string_rjust(
struct screen_write_ctx *ctx, const char *fmt, ...)
{
struct screen *s = ctx->s;
va_list ap;
size_t size;
char *msg, *ptr;
va_start(ap, fmt);
size = vasprintf(&msg, fmt, ap);
va_end(ap);
ptr = msg;
if (size > screen_size_x(s)) {
ptr += size - screen_size_x(s);
size = screen_size_x(s);
}
screen_write_move_cursor(ctx, screen_size_x(s) - size, s->cy);
for (; *ptr != '\0'; ptr++) {
if (s->cx == screen_size_x(s))
break;
screen_write_put_character(ctx, *ptr);
}
xfree(msg);
return (size);
}
/* Put a string, truncating at end of line. */
void printflike2
screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...)
{
struct screen *s = ctx->s;
va_list ap;
char *msg, *ptr;
va_start(ap, fmt);
vasprintf(&msg, fmt, ap);
va_end(ap);
for (ptr = msg; *ptr != '\0'; ptr++) {
if (s->cx == screen_size_x(s))
break;
screen_write_put_character(ctx, *ptr);
}
xfree(msg);
}
/* Set screen attributes. */
void
screen_write_set_attributes(
struct screen_write_ctx *ctx, u_char attr, u_char colr)
{
struct screen *s = ctx->s;
if (s->attr != attr || s->colr != colr) {
s->attr = attr;
s->colr = colr;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr);
}
}
/* Set scroll region. */
void
screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower)
{
struct screen *s = ctx->s;
screen_write_limit(upper, 0, screen_last_y(s));
screen_write_limit(lower, 0, screen_last_y(s));
if (upper > lower)
return;
/* Cursor moves to top-left. */
s->cx = 0;
s->cy = upper;
s->rupper = upper;
s->rlower = lower;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
}
/* Move cursor up and scroll if necessary. */
void
screen_write_cursor_up_scroll(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
if (s->cy == s->rupper)
screen_display_scroll_region_down(s);
else if (s->cy > 0)
s->cy--;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_REVERSEINDEX);
}
/* Move cursor down and scroll if necessary */
void
screen_write_cursor_down_scroll(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
if (s->cy == s->rlower)
screen_display_scroll_region_up(s);
else if (s->cy < screen_last_y(s))
s->cy++;
if (ctx->write != NULL) /* XXX FORWARDINDEX */
ctx->write(ctx->data, TTY_CHARACTER, '\n');
}
/* Move cursor up. */
void
screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_above_y(s, s->cy) - 1);
s->cy -= n;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
/* Move cursor down. */
void
screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_below_y(s, s->cy) - 1);
s->cy += n;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
/* Move cursor left. */
void
screen_write_cursor_left(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_left_x(s, s->cx) - 1);
s->cx -= n;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
/* Move cursor right. */
void
screen_write_cursor_right(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_right_x(s, s->cx) - 1);
s->cx += n;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
/* Delete lines. */
void
screen_write_delete_lines(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_below_y(s, s->cy));
if (s->cy < s->rupper || s->cy > s->rlower)
screen_display_delete_lines(s, s->cy, n);
else
screen_display_delete_lines_region(s, s->cy, n);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_DELETELINE, n);
}
/* Delete characters. */
void
screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_right_x(s, s->cx));
screen_display_delete_characters(s, s->cx, s->cy, n);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_DELETECHARACTER, n);
}
/* Insert lines. */
void
screen_write_insert_lines(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_below_y(s, s->cy));
if (s->cy < s->rupper || s->cy > s->rlower)
screen_display_insert_lines(s, s->cy, n);
else
screen_display_insert_lines_region(s, s->cy, n);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_INSERTLINE, n);
}
/* Insert characters. */
void
screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n)
{
struct screen *s = ctx->s;
screen_write_limit(n, 1, screen_right_x(s, s->cx));
screen_display_insert_characters(s, s->cx, s->cy, n);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_INSERTCHARACTER, n);
}
/* Move the cursor. */
void
screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m)
{
struct screen *s = ctx->s;
screen_write_limit(n, 0, screen_last_x(s));
screen_write_limit(m, 0, screen_last_y(s));
s->cx = n;
s->cy = m;
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
/* Full to end of screen. */
void
screen_write_fill_end_of_screen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
u_int i;
screen_fill_area(s, s->cx, s->cy,
screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr);
screen_fill_area(s, 0, s->cy + 1,
screen_below_y(s, s->cy + 1), 1, SCREEN_DEFDATA, s->attr, s->colr);
if (ctx->write != NULL) {
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
for (i = s->cy + 1; i < screen_size_y(s); i++) {
ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
}
/* Fill entire screen. */
void
screen_write_fill_screen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
u_int i;
screen_display_fill_area(s, 0, 0, screen_size_x(s), screen_size_y(s),
SCREEN_DEFDATA, s->attr, s->colr);
if (ctx->write != NULL) {
for (i = 0; i < screen_size_y(s); i++) {
ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
}
}
/* Fill to end of line. */
void
screen_write_fill_end_of_line(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
screen_display_fill_area(s, s->cx, s->cy,
screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
/* Fill to start of line. */
void
screen_write_fill_start_of_line(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
screen_display_fill_area(s, 0, s->cy,
screen_left_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CLEARSTARTOFLINE);
}
/* Fill entire line. */
void
screen_write_fill_line(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
screen_display_fill_area(s, 0, s->cy,
screen_size_x(s), s->cy, SCREEN_DEFDATA, s->attr, s->colr);
if (ctx->write != NULL)
ctx->write(ctx->data, TTY_CLEARLINE);
}
/* Set a screen mode. */
void
screen_write_set_mode(struct screen_write_ctx *ctx, int mode)
{
struct screen *s = ctx->s;
s->mode |= mode;
if (ctx->write == NULL)
return;
if (mode & MODE_INSERT)
ctx->write(ctx->data, TTY_INSERTON);
if (mode & MODE_KCURSOR)
ctx->write(ctx->data, TTY_KCURSORON);
if (mode & MODE_KKEYPAD)
ctx->write(ctx->data, TTY_KKEYPADON);
if (mode & MODE_MOUSE)
ctx->write(ctx->data, TTY_MOUSEON);
}
/* Clear a screen mode. */
void
screen_write_clear_mode(struct screen_write_ctx *ctx, int mode)
{
struct screen *s = ctx->s;
s->mode &= ~mode;
if (ctx->write == NULL)
return;
if (mode & MODE_INSERT)
ctx->write(ctx->data, TTY_INSERTOFF);
if (mode & MODE_KCURSOR)
ctx->write(ctx->data, TTY_KCURSOROFF);
if (mode & MODE_KKEYPAD)
ctx->write(ctx->data, TTY_KKEYPADOFF);
if (mode & MODE_MOUSE)
ctx->write(ctx->data, TTY_MOUSEOFF);
}
/* Copy cells from another screen. */
void
screen_write_copy_area(struct screen_write_ctx *ctx,
struct screen *src, u_int nx, u_int ny, u_int ox, u_int oy)
{
struct screen *s = ctx->s;
struct screen_redraw_ctx rctx;
int saved_mode;
screen_write_limit(nx, 1, screen_right_x(s, s->cx));
screen_write_limit(ny, 1, screen_below_y(s, s->cy));
screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy);
if (ctx->write != NULL) {
/* Save mode XXX hack */
saved_mode = ctx->s->mode;
ctx->s->mode &= ~MODE_CURSOR;
screen_redraw_start(&rctx, ctx->s, ctx->write, ctx->data);
screen_redraw_area(&rctx, s->cx, s->cy, nx, ny);
screen_redraw_stop(&rctx);
ctx->s->mode = saved_mode;
}
}

450
screen.c
View File

@ -1,4 +1,4 @@
/* $Id: screen.c,v 1.55 2007-12-02 18:23:10 nicm Exp $ */ /* $Id: screen.c,v 1.56 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,6 +24,54 @@
/* /*
* Virtual screen. * Virtual screen.
*
* A screen is stored as three arrays of lines of 8-bit values, one for the
* actual characters (data), one for attributes and one for colours. Three
* seperate blocks means memset and friends can be used. Each array is y by x
* in size, row then column order. Sizes are 0-based. There is an additional
* array of u_ints with the size of each line.
*
* Each screen has a history starting at the beginning of the arrays and
* extending for hsize lines. Beyond that is the screen display of size
* dy:
*
* ----------- array base
* | |
* | history |
* ----------- array base + hsize
* | |
* | display |
* | |
* ----------- array base + hsize + dy
*
* The screen_x/screen_y macros are used to convert a cell on the displayed
* area to an absolute position in the arrays.
*
* Screen handling code is split into four files:
*
* screen.c: Creation/deletion, utility functions, and basic functions to
* manipulate the screen based on offsets from the base.
* screen-display.c: Basic functions for manipulating the displayed
* part of the screen. x,y coordinates passed to these
* are relative to the display. These are largely
* utility functions for screen-write.c.
* screen-redraw.c: Functions for redrawing all or part of a screen to
* one or more ttys. A context is filled via one of the
* screen_redraw_start* variants which sets up (removes
* cursor etc) and figures out which tty_write_* function
* to use to write to the terminals, then the other
* screen_redraw_* functions are used to draw the screen,
* and screen_redraw_stop used to reset the cursor and
* clean up. These are used when changing window and a
* few other bits (status line).
* screen-write.c: Functions for modifying (writing into) the screen and
* optionally simultaneously updating one or more ttys.
* These are used in much the same way as the redraw
* functions. These are used to update when parsing
* input from the window (input.c) and for the various
* other modes which maintain private screens.
*
* If you're thinking this all seems too complicated, that's because it is :-/.
*/ */
/* Colour to string. */ /* Colour to string. */
@ -104,6 +152,8 @@ screen_create(struct screen *s, u_int dx, u_int dy)
s->grid_colr = xmalloc(dy * (sizeof *s->grid_colr)); s->grid_colr = xmalloc(dy * (sizeof *s->grid_colr));
s->grid_size = xmalloc(dy * (sizeof *s->grid_size)); s->grid_size = xmalloc(dy * (sizeof *s->grid_size));
screen_make_lines(s, 0, dy); screen_make_lines(s, 0, dy);
screen_clear_selection(s);
} }
/* Resize screen. */ /* Resize screen. */
@ -122,11 +172,11 @@ screen_resize(struct screen *s, u_int sx, u_int sy)
if (sx == ox && sy == oy) if (sx == ox && sy == oy)
return; return;
/* /*
* X dimension. * X dimension.
*/ */
if (sx != ox) { if (sx != ox) {
/* /*
* If getting smaller, nuke any data in lines over the new * If getting smaller, nuke any data in lines over the new
* size. * size.
*/ */
@ -163,10 +213,10 @@ screen_resize(struct screen *s, u_int sx, u_int sy)
screen_free_lines(s, s->hsize, my); screen_free_lines(s, s->hsize, my);
screen_move_lines(s, s->hsize, s->hsize + my, oy - my); screen_move_lines(s, s->hsize, s->hsize + my, oy - my);
s->cy -= my; s->cy -= my;
oy -= my; oy -= my;
} }
ny = oy - sy; ny = oy - sy;
if (ny > 0) { if (ny > 0) {
@ -178,7 +228,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy)
s->cy = sy - 1; s->cy = sy - 1;
} }
} }
/* Resize line arrays. */ /* Resize line arrays. */
ny = s->hsize + sy; ny = s->hsize + sy;
s->grid_data = xrealloc(s->grid_data, ny, sizeof *s->grid_data); s->grid_data = xrealloc(s->grid_data, ny, sizeof *s->grid_data);
@ -237,6 +287,9 @@ screen_get_cell(struct screen *s,
*attr = s->grid_attr[cy][cx]; *attr = s->grid_attr[cy][cx];
*colr = s->grid_colr[cy][cx]; *colr = s->grid_colr[cy][cx];
} }
if (screen_check_selection(s, cx, cy))
*attr |= ATTR_REVERSE;
} }
/* Set a cell. */ /* Set a cell. */
@ -268,331 +321,6 @@ 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. */
void
screen_draw_start(struct screen_draw_ctx *ctx, struct screen *s,
void (*write)(void *, int, ...), void *data, u_int ox, u_int oy)
{
ctx->write = write;
ctx->data = data;
ctx->s = s;
ctx->ox = ox;
ctx->oy = oy;
/* Resetting the scroll region homes the cursor so start at 0,0. */
ctx->cx = 0;
ctx->cy = 0;
ctx->sel.flag = 0;
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr);
ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s));
ctx->write(ctx->data, TTY_CURSOROFF);
ctx->write(ctx->data, TTY_MOUSEOFF);
}
/* Set offset. */
void
screen_draw_set_offset(struct screen_draw_ctx *ctx, u_int ox, u_int oy)
{
ctx->ox = ox;
ctx->oy = oy;
}
/* Set selection. */
void
screen_draw_set_selection(struct screen_draw_ctx *ctx,
int flag, u_int sx, u_int sy, u_int ex, u_int ey)
{
struct screen_draw_sel *sel = &ctx->sel;
sel->flag = flag;
if (!sel->flag)
return;
if (ey < sy || (sy == ey && ex < sx)) {
sel->sx = ex; sel->sy = ey;
sel->ex = sx; sel->ey = sy;
} else {
sel->sx = sx; sel->sy = sy;
sel->ex = ex; sel->ey = ey;
}
}
/* Check if cell in selection. */
int
screen_draw_check_selection(struct screen_draw_ctx *ctx, u_int px, u_int py)
{
struct screen_draw_sel *sel = &ctx->sel;
if (!sel->flag)
return (0);
if (py < sel->sy || py > sel->ey)
return (0);
if (py == sel->sy && py == sel->ey) {
if (px < sel->sx || px > sel->ex)
return (0);
return (1);
}
if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex))
return (0);
return (1);
}
/* Get cell data during drawing. */
void
screen_draw_get_cell(struct screen_draw_ctx *ctx,
u_int px, u_int py, u_char *data, u_char *attr, u_char *colr)
{
struct screen *s = ctx->s;
u_int cx, cy;
cx = ctx->ox + px;
cy = screen_y(s, py) - ctx->oy;
screen_get_cell(s, cx, cy, data, attr, colr);
if (screen_draw_check_selection(ctx, cx, cy))
*attr |= ATTR_REVERSE;
}
/* Finalise drawing. */
void
screen_draw_stop(struct screen_draw_ctx *ctx)
{
struct screen *s = ctx->s;
ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
if (ctx->cx != s->cx || ctx->cy != s->cy)
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr);
if (s->mode & MODE_BACKGROUND) {
if (s->mode & MODE_BGCURSOR)
ctx->write(ctx->data, TTY_CURSORON);
} else {
if (s->mode & MODE_CURSOR)
ctx->write(ctx->data, TTY_CURSORON);
}
if (s->mode & MODE_MOUSE)
ctx->write(ctx->data, TTY_MOUSEON);
}
/* 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;
screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
for (i = 0; i < screen_size_y(ctx->s); i++) {
screen_draw_move_cursor(ctx, 0, i);
screen_draw_clear_line_to(ctx, screen_size_x(ctx->s));
}
}
/* Write string. */
void printflike2
screen_draw_write_string(struct screen_draw_ctx *ctx, const char *fmt, ...)
{
struct screen *s = ctx->s;
va_list ap;
char *msg, *ptr;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
for (ptr = msg; *ptr != '\0'; ptr++) {
if (ctx->cx > screen_last_x(s))
break;
ctx->write(ctx->data, TTY_CHARACTER, *ptr);
ctx->cx++;
}
xfree(msg);
}
/* Move cursor. */
void
screen_draw_move_cursor(struct screen_draw_ctx *ctx, u_int px, u_int py)
{
if (px == ctx->cx && py == ctx->cy)
return;
if (px == 0 && py == ctx->cy)
ctx->write(ctx->data, TTY_CHARACTER, '\r');
else if (px == ctx->cx && py == ctx->cy + 1)
ctx->write(ctx->data, TTY_CHARACTER, '\n');
else if (px == 0 && py == ctx->cy + 1) {
ctx->write(ctx->data, TTY_CHARACTER, '\r');
ctx->write(ctx->data, TTY_CHARACTER, '\n');
} else
ctx->write(ctx->data, TTY_CURSORMOVE, py, px);
ctx->cx = px;
ctx->cy = py;
}
/* Set attributes. */
void
screen_draw_set_attributes(
struct screen_draw_ctx *ctx, u_char attr, u_char colr)
{
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr);
}
/* Draw single cell. */
void
screen_draw_cell(struct screen_draw_ctx *ctx, u_int px, u_int py)
{
u_char data, attr, colr;
screen_draw_move_cursor(ctx, px, py);
screen_draw_get_cell(ctx, px, py, &data, &attr, &colr);
screen_draw_set_attributes(ctx, attr, colr);
ctx->write(ctx->data, TTY_CHARACTER, data);
/*
* Don't try to wrap as it will cause problems when screen is smaller
* than client.
*/
ctx->cx++;
}
/* Draw range of cells. */
void
screen_draw_cells(struct screen_draw_ctx *ctx, u_int px, u_int py, u_int nx)
{
u_int i;
for (i = px; i < px + nx; i++)
screen_draw_cell(ctx, i, py);
}
/* Draw single column. */
void
screen_draw_column(struct screen_draw_ctx *ctx, u_int px)
{
u_int i;
for (i = 0; i < screen_size_y(ctx->s); i++)
screen_draw_cell(ctx, px, i);
}
/* Draw single line. */
void
screen_draw_line(struct screen_draw_ctx *ctx, u_int py)
{
u_int cx, cy;
cy = screen_y(ctx->s, py) - ctx->oy;
cx = ctx->s->grid_size[cy];
if (ctx->sel.flag ||
screen_size_x(ctx->s) < 5 || cx >= screen_size_x(ctx->s) - 5)
screen_draw_cells(ctx, 0, py, screen_size_x(ctx->s));
else {
screen_draw_cells(ctx, 0, py, cx);
screen_draw_move_cursor(ctx, cx, py);
screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
}
/* Draw set of lines. */
void
screen_draw_lines(struct screen_draw_ctx *ctx, u_int py, u_int ny)
{
u_int i;
for (i = py; i < py + ny; i++)
screen_draw_line(ctx, i);
}
/* Draw entire screen. */
void
screen_draw_screen(struct screen_draw_ctx *ctx)
{
screen_draw_lines(ctx, 0, screen_size_y(ctx->s));
}
/* Create a range of lines. */ /* Create a range of lines. */
void void
screen_make_lines(struct screen *s, u_int py, u_int ny) screen_make_lines(struct screen *s, u_int py, u_int ny)
@ -641,24 +369,60 @@ screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny)
&s->grid_size[dy], &s->grid_size[py], ny * (sizeof *s->grid_size)); &s->grid_size[dy], &s->grid_size[py], ny * (sizeof *s->grid_size));
} }
/* Fill a range of lines. */ /* Fill an area. */
void void
screen_fill_lines( screen_fill_area(struct screen *s, u_int px, u_int py,
struct screen *s, u_int py, u_int ny, u_char data, u_char attr, u_char colr) u_int nx, u_int ny, u_char data, u_char attr, u_char colr)
{ {
u_int i; u_int i, j;
for (i = py; i < py + ny; i++) for (i = py; i < py + ny; i++) {
screen_fill_cells(s, 0, i, s->dx, data, attr, colr); for (j = px; j < px + nx; j++)
screen_set_cell(s, j, i, data, attr, colr);
}
} }
/* Fill a range of cells. */ /* Set selection. */
void void
screen_fill_cells(struct screen *s, screen_set_selection(struct screen *s, u_int sx, u_int sy, u_int ex, u_int ey)
u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr)
{ {
u_int i; struct screen_sel *sel = &s->sel;
for (i = px; i < px + nx; i++) sel->flag = 1;
screen_set_cell(s, i, py, data, attr, colr); if (ey < sy || (sy == ey && ex < sx)) {
sel->sx = ex; sel->sy = ey;
sel->ex = sx; sel->ey = sy;
} else {
sel->sx = sx; sel->sy = sy;
sel->ex = ex; sel->ey = ey;
}
}
/* Clear selection. */
void
screen_clear_selection(struct screen *s)
{
struct screen_sel *sel = &s->sel;
sel->flag = 0;
}
/* Check if cell in selection. */
int
screen_check_selection(struct screen *s, u_int px, u_int py)
{
struct screen_sel *sel = &s->sel;
if (!sel->flag || py < sel->sy || py > sel->ey)
return (0);
if (py == sel->sy && py == sel->ey) {
if (px < sel->sx || px > sel->ex)
return (0);
return (1);
}
if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex))
return (0);
return (1);
} }

View File

@ -1,4 +1,4 @@
/* $Id: server-fn.c,v 1.35 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: server-fn.c,v 1.36 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -71,7 +71,7 @@ server_extract_session(struct msg_command_data *data, char *name, char **cause)
xasprintf(cause, "multiple sessions and session not specified"); xasprintf(cause, "multiple sessions and session not specified");
return (NULL); return (NULL);
} }
return (s); return (s);
} }
void void
@ -123,11 +123,12 @@ server_write_window(
void void
server_clear_client(struct client *c) server_clear_client(struct client *c)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
screen_draw_start_client(&ctx, c, 0, 0); screen_redraw_start_client(&ctx, c);
screen_draw_clear_screen(&ctx); screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
screen_draw_stop(&ctx); screen_redraw_clear_screen(&ctx);
screen_redraw_stop(&ctx);
status_write_client(c); status_write_client(c);
} }
@ -135,12 +136,11 @@ server_clear_client(struct client *c)
void void
server_redraw_client(struct client *c) server_redraw_client(struct client *c)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
struct window *w = c->session->curw->window;
screen_draw_start_client(&ctx, c, 0, 0); screen_redraw_start_client(&ctx, c);
window_draw(w, &ctx, 0, screen_size_y(&w->screen)); screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
status_write_client(c); status_write_client(c);
} }
@ -154,11 +154,12 @@ server_status_client(struct client *c)
void void
server_clear_session(struct session *s) server_clear_session(struct session *s)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
screen_draw_start_session(&ctx, s, 0, 0); screen_redraw_start_session(&ctx, s);
screen_draw_clear_screen(&ctx); screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
screen_draw_stop(&ctx); screen_redraw_clear_screen(&ctx);
screen_redraw_stop(&ctx);
status_write_session(s); status_write_session(s);
} }
@ -166,12 +167,11 @@ server_clear_session(struct session *s)
void void
server_redraw_session(struct session *s) server_redraw_session(struct session *s)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
struct window *w = s->curw->window;
screen_draw_start_session(&ctx, s, 0, 0); screen_redraw_start_session(&ctx, s);
window_draw(w, &ctx, 0, screen_size_y(&w->screen)); screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
status_write_session(s); status_write_session(s);
} }
@ -185,11 +185,12 @@ server_status_session(struct session *s)
void void
server_clear_window(struct window *w) server_clear_window(struct window *w)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
screen_draw_start_window(&ctx, w, 0, 0); screen_redraw_start_window(&ctx, w);
screen_draw_clear_screen(&ctx); screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
screen_draw_stop(&ctx); screen_redraw_clear_screen(&ctx);
screen_redraw_stop(&ctx);
status_write_window(w); status_write_window(w);
} }
@ -197,11 +198,11 @@ server_clear_window(struct window *w)
void void
server_redraw_window(struct window *w) server_redraw_window(struct window *w)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
screen_draw_start_window(&ctx, w, 0, 0); screen_redraw_start_window(&ctx, w);
window_draw(w, &ctx, 0, screen_size_y(&w->screen)); screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
status_write_window(w); status_write_window(w);
} }
@ -228,36 +229,36 @@ server_status_window(struct window *w)
void printflike2 void printflike2
server_write_message(struct client *c, const char *fmt, ...) server_write_message(struct client *c, const char *fmt, ...)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
va_list ap; va_list ap;
char *msg; char *msg;
size_t size; size_t size;
screen_draw_start_client(&ctx, c, 0, 0); screen_redraw_start_client(&ctx, c);
screen_draw_move_cursor(&ctx, 0, c->sy - 1); screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
screen_draw_set_attributes(&ctx, ATTR_REVERSE, 0x88); screen_redraw_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);
size = strlen(msg); size = strlen(msg);
if (size < c->sx - 1) { if (size < c->sx - 1) {
msg = xrealloc(msg, 1, c->sx); msg = xrealloc(msg, 1, c->sx);
msg[c->sx - 1] = '\0'; msg[c->sx - 1] = '\0';
memset(msg + size, SCREEN_DEFDATA, (c->sx - 1) - size); memset(msg + size, SCREEN_DEFDATA, (c->sx - 1) - size);
} }
screen_draw_write_string(&ctx, "%s", msg); screen_redraw_write_string(&ctx, "%s", msg);
xfree(msg); xfree(msg);
buffer_flush(c->tty.fd, c->tty.in, c->tty.out); buffer_flush(c->tty.fd, c->tty.in, c->tty.out);
usleep(750000); usleep(750000);
if (status_lines == 0) { if (status_lines == 0) {
window_draw(c->session->curw->window, &ctx, c->sy - 1, 1); screen_redraw_lines(&ctx, c->sy - 1, 1);
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
} else { } else {
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
status_write_client(c); status_write_client(c);
} }
} }

View File

@ -1,5 +1,5 @@
/* $Id: server-msg.c,v 1.39 2007-11-27 20:01:30 nicm Exp $ */ /* $Id: server-msg.c,v 1.40 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -38,7 +38,7 @@ void printflike2 server_msg_fn_command_print(
struct server_msg { struct server_msg {
enum hdrtype type; enum hdrtype type;
int (*fn)(struct hdr *, struct client *); int (*fn)(struct hdr *, struct client *);
}; };
const struct server_msg server_msg_table[] = { const struct server_msg server_msg_table[] = {
@ -64,7 +64,7 @@ server_msg_dispatch(struct client *c)
if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size) if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size)
return (0); return (0);
buffer_remove(c->in, sizeof hdr); buffer_remove(c->in, sizeof hdr);
for (i = 0; i < NSERVERMSG; i++) { for (i = 0; i < NSERVERMSG; i++) {
msg = server_msg_table + i; msg = server_msg_table + i;
if (msg->type == hdr.type) { if (msg->type == hdr.type) {
@ -72,7 +72,7 @@ server_msg_dispatch(struct client *c)
return (n); return (n);
break; break;
} }
} }
if (i == NSERVERMSG) if (i == NSERVERMSG)
fatalx("unexpected message"); fatalx("unexpected message");
} }
@ -120,7 +120,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
if (hdr->size < sizeof data) if (hdr->size < sizeof data)
fatalx("bad MSG_COMMAND size"); fatalx("bad MSG_COMMAND size");
buffer_read(c->in, &data, sizeof data); buffer_read(c->in, &data, sizeof data);
name = cmd_recv_string(c->in); name = cmd_recv_string(c->in);
client = cmd_recv_string(c->in); client = cmd_recv_string(c->in);
cmd = cmd_recv(c->in); cmd = cmd_recv(c->in);
@ -147,7 +147,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
} }
} else { } else {
if (client == NULL) { if (client == NULL) {
server_msg_fn_command_error(&ctx, server_msg_fn_command_error(&ctx,
"%s: must specify a client", cmd->entry->name); "%s: must specify a client", cmd->entry->name);
goto out; goto out;
} }
@ -167,7 +167,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
ctx.session = NULL; ctx.session = NULL;
if (cmd->entry->flags & CMD_NOSESSION) { if (cmd->entry->flags & CMD_NOSESSION) {
if (name != NULL) { if (name != NULL) {
server_msg_fn_command_error(&ctx, server_msg_fn_command_error(&ctx,
"%s: cannot specify a session", cmd->entry->name); "%s: cannot specify a session", cmd->entry->name);
goto out; goto out;
} }
@ -179,7 +179,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
xfree(cause); xfree(cause);
goto out; goto out;
} }
} }
cmd_exec(cmd, &ctx); cmd_exec(cmd, &ctx);
cmd_free(cmd); cmd_free(cmd);

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.43 2007-12-04 20:25:17 nicm Exp $ */ /* $Id: server.c,v 1.44 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -107,7 +107,7 @@ server_start(const char *path)
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
if (daemon(1, 1) != 0) if (daemon(1, 1) != 0)
fatal("daemon failed"); fatal("daemon failed");
@ -231,7 +231,7 @@ server_handle_windows(struct pollfd **pfd)
if ((w = ARRAY_ITEM(&windows, i)) != NULL) { if ((w = ARRAY_ITEM(&windows, i)) != NULL) {
if (buffer_poll(*pfd, w->in, w->out) != 0) if (buffer_poll(*pfd, w->in, w->out) != 0)
server_lost_window(w); server_lost_window(w);
else else
server_handle_window(w); server_handle_window(w);
} }
(*pfd)++; (*pfd)++;
@ -371,7 +371,7 @@ server_lost_client(struct client *c)
if (ARRAY_ITEM(&clients, i) == c) if (ARRAY_ITEM(&clients, i) == c)
ARRAY_SET(&clients, i, NULL); ARRAY_SET(&clients, i, NULL);
} }
tty_free(&c->tty); tty_free(&c->tty);
close(c->fd); close(c->fd);

View File

@ -1,4 +1,4 @@
/* $Id: session.c,v 1.29 2007-11-12 16:39:30 nicm Exp $ */ /* $Id: session.c,v 1.30 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,7 +26,7 @@
#include "tmux.h" #include "tmux.h"
/* Global session list. */ /* Global session list. */
struct sessions sessions; struct sessions sessions;
void void
session_cancelbell(struct session *s, struct winlink *wl) session_cancelbell(struct session *s, struct winlink *wl)
@ -78,7 +78,7 @@ session_find(const char *name)
if (s != NULL && strcmp(s->name, name) == 0) if (s != NULL && strcmp(s->name, name) == 0)
return (s); return (s);
} }
return (NULL); return (NULL);
} }
@ -131,7 +131,7 @@ session_destroy(struct session *s)
ARRAY_SET(&sessions, i, NULL); ARRAY_SET(&sessions, i, NULL);
while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL) while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL)
ARRAY_TRUNC(&sessions, 1); ARRAY_TRUNC(&sessions, 1);
while (!RB_EMPTY(&s->windows)) while (!RB_EMPTY(&s->windows))
winlink_remove(&s->windows, RB_ROOT(&s->windows)); winlink_remove(&s->windows, RB_ROOT(&s->windows));
@ -163,7 +163,7 @@ session_new(struct session *s, const char *name, const char *cmd, int idx)
fatalx("session not found"); fatalx("session not found");
xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i);
env[0] = buf; env[0] = buf;
if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL) if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL)
return (NULL); return (NULL);
return (session_attach(s, w, idx)); return (session_attach(s, w, idx));
@ -227,7 +227,7 @@ session_next(struct session *s)
return (0); return (0);
} }
/* Move session to previous window. */ /* Move session to previous window. */
int int
session_previous(struct session *s) session_previous(struct session *s)
{ {
@ -247,7 +247,7 @@ session_previous(struct session *s)
return (0); return (0);
} }
/* Move session to specific window. */ /* Move session to specific window. */
int int
session_select(struct session *s, int idx) session_select(struct session *s, int idx)
{ {
@ -264,7 +264,7 @@ session_select(struct session *s, int idx)
return (0); return (0);
} }
/* Move session to last used window. */ /* Move session to last used window. */
int int
session_last(struct session *s) session_last(struct session *s)
{ {
@ -273,7 +273,7 @@ session_last(struct session *s)
wl = s->lastw; wl = s->lastw;
if (wl == NULL) if (wl == NULL)
return (-1); return (-1);
if (wl == s->curw) if (wl == s->curw)
return (1); return (1);
s->lastw = s->curw; s->lastw = s->curw;

View File

@ -1,4 +1,4 @@
/* $Id: status.c,v 1.14 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: status.c,v 1.15 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,16 +27,16 @@ void printflike3 status_print(struct buffer *, size_t *, const char *, ...);
void void
status_write_client(struct client *c) status_write_client(struct client *c)
{ {
struct screen_draw_ctx ctx; struct screen_redraw_ctx ctx;
struct winlink *wl; struct winlink *wl;
char flag; char flag;
if (status_lines == 0 || c->sy <= status_lines) if (status_lines == 0 || c->sy <= status_lines)
return; return;
screen_draw_start_client(&ctx, c, 0, 0); screen_redraw_start_client(&ctx, c);
screen_draw_move_cursor(&ctx, 0, c->sy - status_lines); screen_redraw_move_cursor(&ctx, 0, c->sy - status_lines);
screen_draw_set_attributes(&ctx, 0, status_colour); screen_redraw_set_attributes(&ctx, 0, status_colour);
RB_FOREACH(wl, winlinks, &c->session->windows) { RB_FOREACH(wl, winlinks, &c->session->windows) {
flag = ' '; flag = ' ';
@ -46,15 +46,15 @@ status_write_client(struct client *c)
flag = '*'; flag = '*';
if (session_hasbell(c->session, wl)) if (session_hasbell(c->session, wl))
flag = '!'; flag = '!';
screen_draw_write_string( screen_redraw_write_string(
&ctx, "%d:%s%c ", wl->idx, wl->window->name, flag); &ctx, "%d:%s%c ", wl->idx, wl->window->name, flag);
if (ctx.cx >= screen_last_x(ctx.s)) if (ctx.s->cx >= screen_last_x(ctx.s))
break; break;
} }
screen_draw_clear_line_to(&ctx, screen_last_x(ctx.s)); screen_redraw_clear_end_of_line(&ctx);
screen_draw_stop(&ctx); screen_redraw_stop(&ctx);
} }
void void
@ -63,7 +63,7 @@ status_write_window(struct window *w)
struct client *c; struct client *c;
u_int i; u_int i;
if (w->screen.mode & MODE_HIDDEN) if (w->flags & WINDOW_HIDDEN)
return; return;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {

10
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.44 2007-11-23 17:52:54 nicm Exp $ */ /* $Id: tmux.c,v 1.45 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -141,10 +141,10 @@ void
sigreset(void) sigreset(void)
{ {
struct sigaction act; struct sigaction act;
memset(&act, 0, sizeof act); memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_handler = SIG_DFL; act.sa_handler = SIG_DFL;
if (sigaction(SIGPIPE, &act, NULL) != 0) if (sigaction(SIGPIPE, &act, NULL) != 0)
fatal("sigaction failed"); fatal("sigaction failed");
@ -283,7 +283,7 @@ main(int argc, char **argv)
pfd.events = POLLIN; pfd.events = POLLIN;
if (BUFFER_USED(cctx.srv_out) > 0) if (BUFFER_USED(cctx.srv_out) > 0)
pfd.events |= POLLOUT; pfd.events |= POLLOUT;
if (poll(&pfd, 1, INFTIM) == -1) { if (poll(&pfd, 1, INFTIM) == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
@ -316,7 +316,7 @@ main(int argc, char **argv)
if (hdr.size > INT_MAX - 1) if (hdr.size > INT_MAX - 1)
fatalx("bad MSG_ERROR size"); fatalx("bad MSG_ERROR size");
log_warnx("%.*s", log_warnx("%.*s",
(int) hdr.size, BUFFER_OUT(cctx.srv_in)); (int) hdr.size, BUFFER_OUT(cctx.srv_in));
buffer_remove(cctx.srv_in, hdr.size); buffer_remove(cctx.srv_in, hdr.size);
n = 1; n = 1;
goto out; goto out;

215
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.108 2007-12-02 18:23:10 nicm Exp $ */ /* $Id: tmux.h,v 1.109 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -281,7 +281,7 @@ struct buffer {
#define TTY_KKEYPADON 23 #define TTY_KKEYPADON 23
#define TTY_TITLE 24 #define TTY_TITLE 24
#define TTY_MOUSEON 25 #define TTY_MOUSEON 25
#define TTY_MOUSEOFF 26 /* XXX merge allon/off into 1 arg? */ #define TTY_MOUSEOFF 26 /* XXX merge allon/off into 1 arg? */
/* Message codes. */ /* Message codes. */
enum hdrtype { enum hdrtype {
@ -335,23 +335,25 @@ struct msg_resize_data {
#define ATTR_CHARSET 0x80 /* alternative character set */ #define ATTR_CHARSET 0x80 /* alternative character set */
/* Modes. */ /* Modes. */
#define MODE_CURSOR 0x001 #define MODE_CURSOR 0x01
#define MODE_INSERT 0x002 #define MODE_INSERT 0x02
#define MODE_KCURSOR 0x004 #define MODE_KCURSOR 0x04
#define MODE_KKEYPAD 0x008 #define MODE_KKEYPAD 0x08
#define MODE_SAVED 0x010 #define MODE_SAVED 0x10
#define MODE_HIDDEN 0x020 #define MODE_MOUSE 0x20
#define MODE_BACKGROUND 0x040
#define MODE_BGCURSOR 0x080
#define MODE_MOUSE 0x100
/* /* Screen selection. */
* Virtual screen. This is stored as three blocks of 8-bit values, one for struct screen_sel {
* the actual characters, one for attributes and one for colours. Three int flag;
* seperate blocks means memset and friends can be used.
* u_int sx;
* Each block is y by x in size, row then column order. Sizes are 0-based. u_int sy;
*/
u_int ex;
u_int ey;
};
/* Virtual screen. */
struct screen { struct screen {
char *title; char *title;
@ -378,35 +380,29 @@ struct screen {
u_int saved_cy; u_int saved_cy;
u_char saved_attr; u_char saved_attr;
u_char saved_colr; u_char saved_colr;
int mode; int mode;
};
/* Screen redraw selection. */ struct screen_sel sel;
struct screen_draw_sel {
int flag;
u_int sx;
u_int sy;
u_int ex;
u_int ey;
}; };
/* Screen redraw context. */ /* Screen redraw context. */
struct screen_draw_ctx { struct screen_redraw_ctx {
void *data;
void (*write)(void *, int, ...);
u_int saved_cx;
u_int saved_cy;
struct screen *s;
};
/* Screen write context. */
struct screen_write_ctx {
void *data; void *data;
void (*write)(void *, int, ...); void (*write)(void *, int, ...);
struct screen *s; struct screen *s;
u_int cx;
u_int cy;
u_int ox;
u_int oy;
struct screen_draw_sel sel;
}; };
/* Screen display access macros. */ /* Screen display access macros. */
@ -423,11 +419,20 @@ 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)
/* These are inclusive... */
#define screen_left_x(s, x) ((x) + 1)
#define screen_right_x(s, x) \
((x) < screen_size_x(s) ? screen_size_x(s) - (x) : 0)
#define screen_above_y(s, y) ((y) + 1)
#define screen_below_y(s, y) \
((y) < screen_size_y(s) ? screen_size_y(s) - (y) : 0)
/* Screen default contents. */ /* Screen default contents. */
#define SCREEN_DEFDATA ' ' #define SCREEN_DEFDATA ' '
#define SCREEN_DEFATTR 0 #define SCREEN_DEFATTR 0
#define SCREEN_DEFCOLR 0x88 #define SCREEN_DEFCOLR 0x88
/* Input parser sequence argument. */ /* Input parser sequence argument. */
struct input_arg { struct input_arg {
u_char data[64]; u_char data[64];
@ -437,6 +442,7 @@ struct input_arg {
/* Input parser context. */ /* Input parser context. */
struct input_ctx { struct input_ctx {
struct window *w; struct window *w;
struct screen_write_ctx ctx;
u_char *buf; u_char *buf;
size_t len; size_t len;
@ -462,9 +468,8 @@ struct input_ctx {
*/ */
struct window_mode { struct window_mode {
void (*init)(struct window *); void (*init)(struct window *);
void (*free)(struct window *);
void (*resize)(struct window *, u_int, u_int); void (*resize)(struct window *, 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);
}; };
@ -480,8 +485,10 @@ struct window {
int flags; int flags;
#define WINDOW_BELL 0x1 #define WINDOW_BELL 0x1
#define WINDOW_HIDDEN 0x2
struct screen screen; struct screen *screen;
struct screen base;
const struct window_mode *mode; const struct window_mode *mode;
void *modedata; void *modedata;
@ -661,7 +668,7 @@ void tty_init(struct tty *, char *, char *);
int tty_open(struct tty *, char **); int tty_open(struct tty *, char **);
void tty_close(struct tty *); void tty_close(struct tty *);
void tty_free(struct tty *); void tty_free(struct tty *);
void tty_vwrite(struct tty *, int, va_list); void tty_vwrite(struct tty *, struct screen *s, int, va_list);
/* tty-keys.c */ /* tty-keys.c */
int tty_keys_cmp(struct tty_key *, struct tty_key *); int tty_keys_cmp(struct tty_key *, struct tty_key *);
@ -787,27 +794,13 @@ void input_parse(struct window *);
void input_key(struct window *, int); void input_key(struct window *, int);
/* screen-display.c */ /* screen-display.c */
void screen_display_set_cell(
struct screen *, u_int, u_int, u_char, u_char, u_char);
void screen_display_make_lines(struct screen *, u_int, u_int); void screen_display_make_lines(struct screen *, u_int, u_int);
void screen_display_free_lines(struct screen *, u_int, u_int); void screen_display_free_lines(struct screen *, u_int, u_int);
void screen_display_move_lines(struct screen *, u_int, u_int, u_int); void screen_display_move_lines(struct screen *, u_int, u_int, u_int);
void screen_display_fill_lines( void screen_display_fill_area(struct screen *,
struct screen *, u_int, u_int, u_char, u_char, u_char); u_int, u_int, u_int, u_int, u_char, u_char, u_char);
void screen_display_fill_cells(
struct screen *, u_int, u_int, u_int, u_char, u_char, u_char);
void screen_display_fill_screen(struct screen *, u_char, u_char, u_char);
void screen_display_fill_cursor_eos(
struct screen *, u_char, u_char, u_char);
void screen_display_fill_cursor_bos(
struct screen *, u_char, u_char, u_char);
void screen_display_fill_line(
struct screen *, u_int, u_char, u_char, u_char);
void screen_display_fill_cursor_bol(
struct screen *, u_char, u_char, u_char);
void screen_display_fill_cursor_eol(
struct screen *, u_char, u_char, u_char);
void screen_display_cursor_set(struct screen *, u_char);
void screen_display_cursor_up(struct screen *);
void screen_display_cursor_down(struct screen *);
void screen_display_scroll_region_up(struct screen *); void screen_display_scroll_region_up(struct screen *);
void screen_display_scroll_region_down(struct screen *); void screen_display_scroll_region_down(struct screen *);
void screen_display_insert_lines(struct screen *, u_int, u_int); void screen_display_insert_lines(struct screen *, u_int, u_int);
@ -816,6 +809,64 @@ void screen_display_delete_lines(struct screen *, u_int, u_int);
void screen_display_delete_lines_region(struct screen *, u_int, u_int); void screen_display_delete_lines_region(struct screen *, u_int, u_int);
void screen_display_insert_characters(struct screen *, u_int, u_int, u_int); void screen_display_insert_characters(struct screen *, u_int, u_int, u_int);
void screen_display_delete_characters(struct screen *, u_int, u_int, u_int); void screen_display_delete_characters(struct screen *, u_int, u_int, u_int);
void screen_display_copy_area(struct screen *, struct screen *,
u_int, u_int, u_int, u_int, u_int, u_int);
/* screen-write.c */
void screen_write_start_window(struct screen_write_ctx *, struct window *);
void screen_write_start_client(struct screen_write_ctx *, struct client *);
void screen_write_start_session(
struct screen_write_ctx *, struct session *);
void screen_write_start(struct screen_write_ctx *,
struct screen *, void (*)(void *, int, ...), void *);
void screen_write_stop(struct screen_write_ctx *);
void screen_write_set_title(struct screen_write_ctx *, char *);
void screen_write_put_character(struct screen_write_ctx *, u_char);
size_t printflike2 screen_write_put_string_rjust(
struct screen_write_ctx *, const char *, ...);
void printflike2 screen_write_put_string(
struct screen_write_ctx *, const char *, ...);
void screen_write_set_attributes(struct screen_write_ctx *, u_char, u_char);
void screen_write_set_region(struct screen_write_ctx *, u_int, u_int);
void screen_write_cursor_up_scroll(struct screen_write_ctx *);
void screen_write_cursor_down_scroll(struct screen_write_ctx *);
void screen_write_cursor_up(struct screen_write_ctx *, u_int);
void screen_write_cursor_down(struct screen_write_ctx *, u_int);
void screen_write_cursor_left(struct screen_write_ctx *, u_int);
void screen_write_cursor_right(struct screen_write_ctx *, u_int);
void screen_write_delete_lines(struct screen_write_ctx *, u_int);
void screen_write_delete_characters(struct screen_write_ctx *, u_int);
void screen_write_insert_lines(struct screen_write_ctx *, u_int);
void screen_write_insert_characters(struct screen_write_ctx *, u_int);
void screen_write_move_cursor(struct screen_write_ctx *, u_int, u_int);
void screen_write_fill_end_of_screen(struct screen_write_ctx *);
void screen_write_fill_screen(struct screen_write_ctx *);
void screen_write_fill_end_of_line(struct screen_write_ctx *);
void screen_write_fill_start_of_line(struct screen_write_ctx *);
void screen_write_fill_line(struct screen_write_ctx *);
void screen_write_set_mode(struct screen_write_ctx *, int);
void screen_write_clear_mode(struct screen_write_ctx *, int);
void screen_write_copy_area(struct screen_write_ctx *,
struct screen *, u_int, u_int, u_int, u_int);
/* screen-redraw.c */
void screen_redraw_start_window(struct screen_redraw_ctx *, struct window *);
void screen_redraw_start_client(struct screen_redraw_ctx *, struct client *);
void screen_redraw_start_session(
struct screen_redraw_ctx *, struct session *);
void screen_redraw_start(struct screen_redraw_ctx *,
struct screen *, void (*)(void *, int, ...), void *);
void screen_redraw_stop(struct screen_redraw_ctx *);
void screen_redraw_move_cursor(struct screen_redraw_ctx *, u_int, u_int);
void screen_redraw_set_attributes(struct screen_redraw_ctx *, u_int, u_int);
void printflike2 screen_redraw_write_string(
struct screen_redraw_ctx *, const char *, ...);
void screen_redraw_clear_end_of_line(struct screen_redraw_ctx *);
void screen_redraw_clear_screen(struct screen_redraw_ctx *);
void screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int);
void screen_redraw_area(
struct screen_redraw_ctx *, u_int, u_int, u_int, u_int);
void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int);
/* screen.c */ /* screen.c */
const char *screen_colourstring(u_char); const char *screen_colourstring(u_char);
@ -828,44 +879,14 @@ 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_window(
struct screen_draw_ctx *, struct window *, u_int, u_int);
void screen_draw_start_client(
struct screen_draw_ctx *, struct client *, u_int, u_int);
void screen_draw_start_session(
struct screen_draw_ctx *, struct session *, u_int, u_int);
void screen_draw_start(struct screen_draw_ctx *, struct screen *s,
void (*)(void *, int, ...), void *, u_int, u_int);
void screen_draw_stop(struct screen_draw_ctx *);
void screen_draw_set_offset(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_set_selection(
struct screen_draw_ctx *, int, u_int, u_int, u_int, u_int);
int screen_draw_check_selection(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_get_cell(struct screen_draw_ctx *,
u_int, u_int, u_char *, u_char *, u_char *);
void screen_draw_insert_characters(struct screen_draw_ctx *, u_int);
void screen_draw_delete_characters(struct screen_draw_ctx *, u_int);
void screen_draw_insert_lines(struct screen_draw_ctx *, u_int);
void screen_draw_delete_lines(struct screen_draw_ctx *, u_int);
void screen_draw_clear_line_to(struct screen_draw_ctx *, u_int);
void screen_draw_clear_screen(struct screen_draw_ctx *);
void printflike2 screen_draw_write_string(
struct screen_draw_ctx *, const char *, ...);
void screen_draw_move_cursor(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_set_attributes(struct screen_draw_ctx *, u_char, u_char);
void screen_draw_cell(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_cells(struct screen_draw_ctx *, u_int, u_int, u_int);
void screen_draw_column(struct screen_draw_ctx *, u_int);
void screen_draw_line(struct screen_draw_ctx *, u_int);
void screen_draw_lines(struct screen_draw_ctx *, u_int, u_int);
void screen_draw_screen(struct screen_draw_ctx *);
void screen_make_lines(struct screen *, u_int, u_int); void screen_make_lines(struct screen *, u_int, u_int);
void screen_free_lines(struct screen *, u_int, u_int); void screen_free_lines(struct screen *, u_int, u_int);
void screen_move_lines(struct screen *, u_int, u_int, u_int); void screen_move_lines(struct screen *, u_int, u_int, u_int);
void screen_fill_lines( void screen_fill_area(struct screen *,
struct screen *, u_int, u_int, u_char, u_char, u_char); u_int, u_int, u_int, u_int, u_char, u_char, u_char);
void screen_fill_cells( void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int);
struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); void screen_clear_selection(struct screen *);
int screen_check_selection(struct screen *, u_int, u_int);
/* window.c */ /* window.c */
extern struct windows windows; extern struct windows windows;
@ -885,8 +906,6 @@ struct window *window_create(
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 *); void window_parse(struct window *);
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 */

View File

@ -1,4 +1,4 @@
/* $Id: tty-keys.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: tty-keys.c,v 1.2 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -259,7 +259,7 @@ tty_keys_next(struct tty *tty, int *code)
} }
xfree(s); xfree(s);
if (tk == NULL) { if (tk == NULL) {
/* /*
* XXX Pass through unchanged. * XXX Pass through unchanged.
*/ */
*code = '\e'; *code = '\e';

View File

@ -1,4 +1,4 @@
/* $Id: tty-write.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: tty-write.c,v 1.2 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,8 +24,7 @@ void
tty_write_client(void *ptr, int cmd, ...) tty_write_client(void *ptr, int cmd, ...)
{ {
struct client *c = ptr; struct client *c = ptr;
va_list ap;
va_list ap;
va_start(ap, cmd); va_start(ap, cmd);
tty_vwrite_client(c, cmd, ap); tty_vwrite_client(c, cmd, ap);
@ -36,8 +35,9 @@ void
tty_vwrite_client(void *ptr, int cmd, va_list ap) tty_vwrite_client(void *ptr, int cmd, va_list ap)
{ {
struct client *c = ptr; struct client *c = ptr;
struct screen *s = c->session->curw->window->screen;
tty_vwrite(&c->tty, cmd, ap); tty_vwrite(&c->tty, s, cmd, ap);
} }
void void
@ -58,7 +58,7 @@ tty_vwrite_window(void *ptr, int cmd, va_list ap)
va_list aq; va_list aq;
u_int i; u_int i;
if (w->screen.mode & MODE_HIDDEN) if (w->flags & WINDOW_HIDDEN)
return; return;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@ -68,8 +68,8 @@ tty_vwrite_window(void *ptr, int cmd, va_list ap)
if (c->session->curw->window != w) if (c->session->curw->window != w)
continue; continue;
va_copy(aq, ap); va_copy(aq, ap);
tty_vwrite(&c->tty, cmd, aq); tty_vwrite_client(c, cmd, aq);
va_end(aq); va_end(aq);
} }
} }
@ -101,7 +101,7 @@ tty_vwrite_session(void *ptr, int cmd, va_list ap)
continue; continue;
va_copy(aq, ap); va_copy(aq, ap);
tty_vwrite(&c->tty, cmd, aq); tty_vwrite_client(c, cmd, aq);
va_end(aq); va_end(aq);
} }
} }

47
tty.c
View File

@ -1,4 +1,4 @@
/* $Id: tty.c,v 1.8 2007-12-03 10:47:27 nicm Exp $ */ /* $Id: tty.c,v 1.9 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -25,7 +25,7 @@
#include <string.h> #include <string.h>
#define TTYDEFCHARS #define TTYDEFCHARS
/* glibc requires unistd.h before termios.h for TTYDEFCHARS. */ /* glibc requires unistd.h before termios.h for TTYDEFCHARS. */
#include <unistd.h> #include <unistd.h>
#include <termios.h> #include <termios.h>
#include "tmux.h" #include "tmux.h"
@ -87,7 +87,7 @@ tty_open(struct tty *tty, char **cause)
tty->colr = SCREEN_DEFCOLR; tty->colr = SCREEN_DEFCOLR;
tty_keys_init(tty); tty_keys_init(tty);
tty_fill_acs(tty); tty_fill_acs(tty);
if (tcgetattr(tty->fd, &tty->tio) != 0) if (tcgetattr(tty->fd, &tty->tio) != 0)
@ -95,7 +95,7 @@ tty_open(struct tty *tty, char **cause)
memset(&tio, 0, sizeof tio); memset(&tio, 0, sizeof tio);
tio.c_iflag = TTYDEF_IFLAG & ~(IXON|IXOFF|ICRNL|INLCR); tio.c_iflag = TTYDEF_IFLAG & ~(IXON|IXOFF|ICRNL|INLCR);
tio.c_oflag = TTYDEF_OFLAG & ~(OPOST|ONLCR|OCRNL|ONLRET); tio.c_oflag = TTYDEF_OFLAG & ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag = tio.c_lflag =
TTYDEF_LFLAG & ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG); TTYDEF_LFLAG & ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG);
tio.c_cflag = TTYDEF_CFLAG; tio.c_cflag = TTYDEF_CFLAG;
memcpy(&tio.c_cc, ttydefchars, sizeof tio.c_cc); memcpy(&tio.c_cc, ttydefchars, sizeof tio.c_cc);
@ -207,10 +207,10 @@ tty_putc(struct tty *tty, char ch)
} }
void void
tty_vwrite(struct tty *tty, int cmd, va_list ap) tty_vwrite(struct tty *tty, unused struct screen *s, int cmd, va_list ap)
{ {
char ch; char ch;
u_int ua, ub; u_int i, ua, ub;
set_curterm(tty->termp); set_curterm(tty->termp);
@ -258,13 +258,36 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap)
tty_puts(tty, tparm(cursor_address, ua, ub)); tty_puts(tty, tparm(cursor_address, ua, ub));
break; break;
case TTY_CLEARENDOFLINE: case TTY_CLEARENDOFLINE:
tty_puts(tty, clr_eol); if (clr_eol != NULL)
tty_puts(tty, clr_eol);
else {
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
for (i = s->cx; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
break; break;
case TTY_CLEARSTARTOFLINE: case TTY_CLEARSTARTOFLINE:
tty_puts(tty, clr_bol); if (clr_bol != NULL)
tty_puts(tty, clr_bol);
else {
tty_puts(tty, tparm(cursor_address, s->cy, 0));
for (i = 0; i < s->cx + 1; i++)
tty_putc(tty, ' ');
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
break; break;
case TTY_CLEARLINE: case TTY_CLEARLINE:
tty_puts(tty, clr_eol); /* XXX */ if (clr_eol != NULL) {
tty_puts(tty, tparm(cursor_address, s->cy, 0));
tty_puts(tty, clr_eol);
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
} else {
tty_puts(tty, tparm(cursor_address, s->cy, 0));
for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
break; break;
case TTY_INSERTLINE: case TTY_INSERTLINE:
ua = va_arg(ap, u_int); ua = va_arg(ap, u_int);
@ -323,6 +346,7 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap)
ub = va_arg(ap, u_int); ub = va_arg(ap, u_int);
tty_puts(tty, tparm(change_scroll_region, ua, ub)); tty_puts(tty, tparm(change_scroll_region, ua, ub));
break; break;
#if 0
case TTY_INSERTON: case TTY_INSERTON:
if (enter_insert_mode != NULL) if (enter_insert_mode != NULL)
tty_puts(tty, enter_insert_mode); tty_puts(tty, enter_insert_mode);
@ -331,7 +355,6 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap)
if (exit_insert_mode != NULL) if (exit_insert_mode != NULL)
tty_puts(tty, exit_insert_mode); tty_puts(tty, exit_insert_mode);
break; break;
#if 0
case TTY_KCURSOROFF: case TTY_KCURSOROFF:
t = tigetstr("CE"); t = tigetstr("CE");
if (t != (char *) 0 && t != (char *) -1) if (t != (char *) 0 && t != (char *) -1)
@ -417,13 +440,13 @@ tty_attributes(struct tty *tty, u_char attr, u_char colr)
if (fg == 8) if (fg == 8)
fg = 7; fg = 7;
} }
if (fg == 8) if (fg == 8)
tty_puts(tty, "\e[39m"); tty_puts(tty, "\e[39m");
else if (set_a_foreground != NULL) else if (set_a_foreground != NULL)
tty_puts(tty, tparm(set_a_foreground, fg)); tty_puts(tty, tparm(set_a_foreground, fg));
} }
bg = colr & 0xf; bg = colr & 0xf;
if (bg != (tty->colr & 0xf)) { if (bg != (tty->colr & 0xf)) {
if (tigetflag("AX") == TRUE) { if (tigetflag("AX") == TRUE) {

View File

@ -1,4 +1,4 @@
/* $Id: window-copy.c,v 1.12 2007-11-27 19:43:50 nicm Exp $ */ /* $Id: window-copy.c,v 1.13 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -23,25 +23,34 @@
#include "tmux.h" #include "tmux.h"
void window_copy_init(struct window *); void window_copy_init(struct window *);
void window_copy_free(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 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_redraw_lines(struct window *, u_int, u_int);
void window_copy_redraw_screen(struct window *);
void window_copy_write_line(
struct window *, struct screen_write_ctx *, u_int);
void window_copy_write_lines(
struct window *, struct screen_write_ctx *, u_int, u_int);
void window_copy_write_column(
struct window *, struct screen_write_ctx *, u_int);
void window_copy_write_columns(
struct window *, struct screen_write_ctx *, u_int, u_int);
void window_copy_update_cursor(struct window *);
void window_copy_start_selection(struct window *);
int window_copy_update_selection(struct window *);
void window_copy_copy_selection(struct window *); void window_copy_copy_selection(struct window *);
void window_copy_copy_line( void window_copy_copy_line(
struct window *, char **, size_t *, size_t *, u_int, u_int, u_int); struct window *, char **, size_t *, size_t *, u_int, u_int, u_int);
u_int window_copy_find_length(struct window *, u_int); u_int window_copy_find_length(struct window *, u_int);
void window_copy_move_cursor(struct window *); void window_copy_cursor_start_of_line(struct window *);
void window_copy_cursor_bol(struct window *); void window_copy_cursor_end_of_line(struct window *);
void window_copy_cursor_eol(struct window *);
void window_copy_cursor_left(struct window *); void window_copy_cursor_left(struct window *);
void window_copy_cursor_right(struct window *); void window_copy_cursor_right(struct window *);
void window_copy_cursor_up(struct window *); void window_copy_cursor_up(struct window *);
void window_copy_cursor_down(struct window *); void window_copy_cursor_down(struct window *);
void window_copy_draw_lines(struct window *, u_int, u_int);
void window_copy_scroll_left(struct window *, u_int); void window_copy_scroll_left(struct window *, u_int);
void window_copy_scroll_right(struct window *, u_int); void window_copy_scroll_right(struct window *, u_int);
void window_copy_scroll_up(struct window *, u_int); void window_copy_scroll_up(struct window *, u_int);
@ -49,106 +58,87 @@ void window_copy_scroll_down(struct window *, u_int);
const struct window_mode window_copy_mode = { const struct window_mode window_copy_mode = {
window_copy_init, window_copy_init,
window_copy_free,
window_copy_resize, window_copy_resize,
window_copy_draw,
window_copy_key window_copy_key
}; };
struct window_copy_mode_data { struct window_copy_mode_data {
struct screen screen;
u_int ox; u_int ox;
u_int oy; u_int oy;
u_int cx;
u_int cy;
u_int size;
int selflag;
u_int selx; u_int selx;
u_int sely; u_int sely;
u_int cx;
u_int cy;
}; };
void void
window_copy_init(struct window *w) window_copy_init(struct window *w)
{ {
struct window_copy_mode_data *data; struct window_copy_mode_data *data;
struct screen *s;
struct screen_write_ctx ctx;
u_int i;
w->modedata = data = xmalloc(sizeof *data); w->modedata = data = xmalloc(sizeof *data);
data->ox = data->oy = 0; data->ox = 0;
data->cx = w->screen.cx; data->oy = 0;
data->cy = w->screen.cy; data->cx = w->base.cx;
data->size = w->screen.hsize; data->cy = w->base.cy;
data->selflag = 0;
s = &data->screen;
w->screen.mode |= (MODE_BACKGROUND|MODE_BGCURSOR); screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base));
s->cx = data->cx;
s->cy = data->cy;
w->screen = s;
screen_write_start(&ctx, s, NULL, NULL);
for (i = 0; i < screen_size_y(s); i++)
window_copy_write_line(w, &ctx, i);
screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
} }
void void
window_copy_resize(unused struct window *w, unused u_int sx, unused u_int sy) window_copy_free(struct window *w)
{
}
void
window_copy_draw_position(struct window *w, struct screen_draw_ctx *ctx)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
char *ptr, buf[32];
size_t len;
len = xsnprintf( w->screen = &w->base;
buf, sizeof buf, "[%u,%u/%u]", data->ox, data->oy, data->size); screen_destroy(&data->screen);
if (len <= screen_size_x(ctx->s))
ptr = buf; w->mode = NULL;
else { xfree(w->modedata);
ptr = buf + len - screen_size_x(ctx->s);
len -= len - screen_size_x(ctx->s);
}
screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len);
screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0);
screen_draw_set_attributes(ctx, 0, status_colour);
screen_draw_write_string(ctx, "%s", ptr);
} }
void void
window_copy_draw( window_copy_resize(struct window *w, u_int sx, u_int sy)
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 = &data->screen;
if (s->hsize != data->size) { screen_resize(s, sx, sy);
data->oy += s->hsize - data->size; screen_display_copy_area(&data->screen, &w->base,
data->size = s->hsize; 0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
} window_copy_update_selection(w);
screen_draw_set_offset(ctx, data->ox, data->oy);
screen_draw_set_selection(ctx,
data->selflag, data->selx, data->sely,
data->cx + data->ox, data->size + data->cy - data->oy);
if (py != 0)
screen_draw_lines(ctx, py, ny);
else {
if (ny > 1)
screen_draw_lines(ctx, py + 1, ny - 1);
window_copy_draw_position(w, ctx);
}
window_copy_move_cursor(w);
} }
void void
window_copy_key(struct window *w, int key) window_copy_key(struct window *w, int key)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
u_int oy, sy; struct screen *s = &data->screen;
sy = screen_size_y(&w->screen);
oy = data->oy;
switch (key) { switch (key) {
case 'Q': case 'Q':
case 'q': case 'q':
goto done; window_copy_free(w);
server_redraw_window(w);
break;
case 'h': case 'h':
case KEYC_LEFT: case KEYC_LEFT:
window_copy_cursor_left(w); window_copy_cursor_left(w);
@ -169,55 +159,199 @@ window_copy_key(struct window *w, int key)
return; return;
case '\025': /* C-u */ case '\025': /* C-u */
case KEYC_PPAGE: case KEYC_PPAGE:
if (data->oy + sy > data->size) if (data->oy + screen_size_y(s) > w->base.hsize)
data->oy = data->size; data->oy = w->base.hsize;
else else
data->oy += sy; data->oy += screen_size_y(s);
window_copy_update_selection(w);
window_copy_redraw_screen(w);
break; break;
case '\006': /* C-f */ case '\006': /* C-f */
case KEYC_NPAGE: case KEYC_NPAGE:
if (data->oy < sy) if (data->oy < screen_size_y(s))
data->oy = 0; data->oy = 0;
else else
data->oy -= sy; data->oy -= screen_size_y(s);
window_copy_update_selection(w);
window_copy_redraw_screen(w);
break; break;
case '\000': /* C-space */ case '\000': /* C-space */
case ' ': case ' ':
data->selflag = !data->selflag; window_copy_start_selection(w);
data->selx = data->cx + data->ox;
data->sely = data->size + data->cy - data->oy;
oy = -1; /* XXX */
break; break;
case '\033': case '\033':
data->selflag = 0; screen_clear_selection(&data->screen);
oy = -1; /* XXX */ break;
break;
case '\027': /* C-w */ case '\027': /* C-w */
case '\r': /* enter */ case '\r': /* enter */
if (data->selflag) window_copy_copy_selection(w);
window_copy_copy_selection(w); window_copy_free(w);
goto done;
case '\001': /* C-a */
window_copy_cursor_bol(w);
return;
case '\005': /* C-e */
window_copy_cursor_eol(w);
return;
}
if (data->oy != oy) {
server_redraw_window(w); server_redraw_window(w);
window_copy_move_cursor(w); break;
case '\001': /* C-a */
window_copy_cursor_start_of_line(w);
break;
case '\005': /* C-e */
window_copy_cursor_end_of_line(w);
break;
} }
return; }
done: void
w->mode = NULL; window_copy_write_line(
xfree(w->modedata); struct window *w, struct screen_write_ctx *ctx, u_int py)
{
w->screen.mode &= ~MODE_BACKGROUND; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
recalculate_sizes(); size_t size;
server_redraw_window(w);
if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour);
screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust(
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
screen_write_set_attributes(
ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
} else
size = 0;
screen_write_move_cursor(ctx, 0, py);
screen_write_copy_area(
ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
}
void
window_copy_write_lines(
struct window *w, struct screen_write_ctx *ctx, u_int py, u_int ny)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
if (py == 0) {
window_copy_write_line(w, ctx, 0);
if (ny == 1)
return;
py++;
ny--;
}
screen_write_move_cursor(ctx, 0, py);
screen_write_copy_area(
ctx, &w->base, screen_size_x(s), ny, data->ox, data->oy);
}
void
window_copy_write_column(
struct window *w, struct screen_write_ctx *ctx, u_int px)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
screen_write_move_cursor(ctx, px, 0);
screen_write_copy_area(
ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
}
void
window_copy_write_columns(
struct window *w, struct screen_write_ctx *ctx, u_int px, u_int nx)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
screen_write_move_cursor(ctx, px, 0);
screen_write_copy_area(
ctx, &w->base, nx, screen_size_y(s), data->ox, data->oy);
}
void
window_copy_redraw_lines(struct window *w, u_int py, u_int ny)
{
struct window_copy_mode_data *data = w->modedata;
struct screen_write_ctx ctx;
u_int i;
screen_write_start_window(&ctx, w);
for (i = py; i < py + ny; i++)
window_copy_write_line(w, &ctx, i);
screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
void
window_copy_redraw_screen(struct window *w)
{
struct window_copy_mode_data *data = w->modedata;
window_copy_redraw_lines(w, 0, screen_size_x(&data->screen));
}
void
window_copy_update_cursor(struct window *w)
{
struct window_copy_mode_data *data = w->modedata;
struct screen_write_ctx ctx;
screen_write_start_window(&ctx, w);
screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
void
window_copy_start_selection(struct window *w)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
data->selx = screen_x(&w->base, data->cx) + data->ox;
data->sely = screen_y(&w->base, data->cy) - data->oy;
s->sel.flag = 1;
window_copy_update_selection(w);
}
int
window_copy_update_selection(struct window *w)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
u_int sx, sy, tx, ty;
if (!s->sel.flag)
return (0);
/* Find top-left of screen. */
tx = screen_x(&w->base, 0) + data->ox;
ty = screen_y(&w->base, 0) - data->oy;
/* Adjust the selection. */
sx = data->selx;
sy = data->sely;
if (sy < ty) {
/* Above it. */
sx = 0;
sy = 0;
} else if (sy > ty + screen_last_y(s)) {
/* Below it. */
sx = screen_last_x(s);
sy = screen_last_y(s);
} else if (sx < tx) {
/* To the left. */
sx = 0;
} else if (sx > tx + screen_last_x(s)) {
/* To the right. */
sx = 0;
sy++;
if (sy > screen_last_y(s))
sy = screen_last_y(s);
} else {
sx -= tx;
sy -= ty;
}
sx = screen_x(s, sx);
sy = screen_x(s, sy);
screen_set_selection(
s, sx, sy, screen_x(s, data->cx), screen_y(s, data->cy));
return (1);
} }
void void
@ -234,9 +368,14 @@ window_copy_copy_selection(struct window *w)
*buf = '\0'; *buf = '\0';
/*
* The selection extends from selx,sely to (adjusted) cx,cy on
* the base screen.
*/
/* Find start and end. */ /* Find start and end. */
xx = data->cx + data->ox; xx = screen_x(&w->base, data->cx) + data->ox;
yy = data->size + data->cy - data->oy; yy = screen_y(&w->base, data->cy) - data->oy;
if (xx < data->selx || (yy == data->sely && xx < data->selx)) { if (xx < data->selx || (yy == data->sely && xx < data->selx)) {
sx = xx; sy = yy; sx = xx; sy = yy;
ex = data->selx; ey = data->sely; ex = data->selx; ey = data->sely;
@ -281,8 +420,7 @@ void
window_copy_copy_line(struct window *w, window_copy_copy_line(struct window *w,
char **buf, size_t *off, size_t *len, u_int sy, u_int sx, u_int ex) char **buf, size_t *off, size_t *len, u_int sy, u_int sx, u_int ex)
{ {
struct screen *s = &w->screen; u_char i, xx;
u_char i, xx;
if (sx > ex) if (sx > ex)
return; return;
@ -296,11 +434,11 @@ window_copy_copy_line(struct window *w,
if (sx < ex) { if (sx < ex) {
for (i = sx; i < ex; i++) { for (i = sx; i < ex; i++) {
*buf = ensure_size(*buf, len, 1, *off + 1); *buf = ensure_size(*buf, len, 1, *off + 1);
(*buf)[*off] = s->grid_data[sy][i]; (*buf)[*off] = w->base.grid_data[sy][i];
(*off)++; (*off)++;
} }
} }
*buf = ensure_size(*buf, len, 1, *off + 1); *buf = ensure_size(*buf, len, 1, *off + 1);
(*buf)[*off] = '\n'; (*buf)[*off] = '\n';
(*off)++; (*off)++;
@ -309,25 +447,16 @@ window_copy_copy_line(struct window *w,
u_int u_int
window_copy_find_length(struct window *w, u_int py) window_copy_find_length(struct window *w, u_int py)
{ {
struct screen *s = &w->screen; u_int px;
u_int px;
px = s->grid_size[py]; px = w->base.grid_size[py];
while (px > 0 && s->grid_data[py][px - 1] == SCREEN_DEFDATA) while (px > 0 && w->base.grid_data[py][px - 1] == SCREEN_DEFDATA)
px--; px--;
return (px); return (px);
} }
void void
window_copy_move_cursor(struct window *w) window_copy_cursor_start_of_line(struct window *w)
{
struct window_copy_mode_data *data = w->modedata;
tty_write_window(w, TTY_CURSORMOVE, data->cy, data->cx);
}
void
window_copy_cursor_bol(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
@ -335,49 +464,52 @@ window_copy_cursor_bol(struct window *w)
window_copy_scroll_right(w, data->ox); window_copy_scroll_right(w, data->ox);
data->cx = 0; data->cx = 0;
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy, 1); window_copy_redraw_lines(w, data->cy, 1);
window_copy_move_cursor(w); else
window_copy_update_cursor(w);
} }
void void
window_copy_cursor_eol(struct window *w) window_copy_cursor_end_of_line(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen; struct screen *s = &data->screen;
u_int xx; u_int px, py;
xx = window_copy_find_length(w, data->size + data->cy - data->oy); py = screen_y(&w->base, data->cy) - data->oy;
px = window_copy_find_length(w, py);
/* On screen. */ /* On screen. */
if (xx > data->ox && xx < data->ox + screen_last_x(s)) if (px > data->ox && px < data->ox + screen_last_x(s))
data->cx = xx - data->ox; data->cx = px - data->ox;
/* Off right of screen. */ /* Off right of screen. */
if (xx > data->ox + screen_last_x(s)) { if (px > data->ox + screen_last_x(s)) {
/* Move cursor to last and scroll screen. */ /* Move cursor to last and scroll screen. */
window_copy_scroll_left(w, window_copy_scroll_left(w,
xx - data->ox - screen_last_x(s)); px - data->ox - screen_last_x(s));
data->cx = screen_last_x(s); data->cx = screen_last_x(s);
} }
/* Off left of screen. */ /* Off left of screen. */
if (xx <= data->ox) { if (px <= data->ox) {
if (xx < screen_last_x(s)) { if (px < screen_last_x(s)) {
/* Short enough to fit on screen. */ /* Short enough to fit on screen. */
window_copy_scroll_right(w, data->ox); window_copy_scroll_right(w, data->ox);
data->cx = xx; data->cx = px;
} else { } else {
/* Too long to fit on screen. */ /* Too long to fit on screen. */
window_copy_scroll_right( window_copy_scroll_right(
w, data->ox - (xx - screen_last_x(s))); w, data->ox - (px - screen_last_x(s)));
data->cx = screen_last_x(s); data->cx = screen_last_x(s);
} }
} }
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy, 1); window_copy_redraw_lines(w, data->cy, 1);
window_copy_move_cursor(w); else
window_copy_update_cursor(w);
} }
void void
@ -385,79 +517,102 @@ window_copy_cursor_left(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
if (data->cx == 0) if (data->cx == 0) {
window_copy_scroll_right(w, 1); if (data->ox > 0)
else { window_copy_scroll_right(w, 1);
else {
window_copy_cursor_up(w);
window_copy_cursor_end_of_line(w);
}
} else {
data->cx--; data->cx--;
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy, 1); window_copy_redraw_lines(w, data->cy, 1);
else
window_copy_update_cursor(w);
} }
window_copy_move_cursor(w);
} }
void void
window_copy_cursor_right(struct window *w) window_copy_cursor_right(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen; u_int px, py;
if (data->cx == screen_last_x(s)) py = screen_y(&w->base, data->cy) - data->oy;
window_copy_scroll_left(w, 1); px = window_copy_find_length(w, py);
else {
if (data->cx >= px) {
window_copy_cursor_start_of_line(w);
window_copy_cursor_down(w);
} else {
data->cx++; data->cx++;
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy, 1); window_copy_redraw_lines(w, data->cy, 1);
else
window_copy_update_cursor(w);
} }
window_copy_move_cursor(w);
} }
void void
window_copy_cursor_up(struct window *w) window_copy_cursor_up(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
u_int ox, oy, px, py;
oy = screen_y(&w->base, data->cy) - data->oy;
ox = window_copy_find_length(w, oy);
if (data->cy == 0) if (data->cy == 0)
window_copy_scroll_down(w, 1); window_copy_scroll_down(w, 1);
else { else {
data->cy--; data->cy--;
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy, 2); window_copy_redraw_lines(w, data->cy, 2);
else
window_copy_update_cursor(w);
} }
window_copy_move_cursor(w);
py = screen_y(&w->base, data->cy) - data->oy;
px = window_copy_find_length(w, py);
if (data->cx > px || data->cx == ox)
window_copy_cursor_end_of_line(w);
} }
void void
window_copy_cursor_down(struct window *w) window_copy_cursor_down(struct window *w)
{ {
struct window_copy_mode_data *data = w->modedata; struct window_copy_mode_data *data = w->modedata;
struct screen *s = &w->screen; struct screen *s = &data->screen;
u_int ox, oy, px, py;
oy = screen_y(&w->base, data->cy) - data->oy;
ox = window_copy_find_length(w, oy);
if (data->cy == screen_last_y(s)) if (data->cy == screen_last_y(s))
window_copy_scroll_up(w, 1); window_copy_scroll_up(w, 1);
else { else {
data->cy++; data->cy++;
if (data->selflag) if (window_copy_update_selection(w))
window_copy_draw_lines(w, data->cy - 1, 2); window_copy_redraw_lines(w, data->cy - 1, 2);
else
window_copy_update_cursor(w);
} }
window_copy_move_cursor(w);
}
void py = screen_y(&w->base, data->cy) - data->oy;
window_copy_draw_lines(struct window *w, u_int py, u_int ny) px = window_copy_find_length(w, py);
{
struct window_copy_mode_data *data = w->modedata;
struct screen_draw_ctx ctx;
screen_draw_start_window(&ctx, w, data->ox, data->oy); if (data->cx > px || data->cx == ox)
window_copy_draw(w, &ctx, py, ny); window_copy_cursor_end_of_line(w);
screen_draw_stop(&ctx);
} }
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_draw_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i; u_int i;
if (data->ox > SHRT_MAX - nx) if (data->ox > SHRT_MAX - nx)
@ -465,26 +620,29 @@ window_copy_scroll_left(struct window *w, u_int nx)
if (nx == 0) if (nx == 0)
return; return;
data->ox += nx; data->ox += nx;
window_copy_update_selection(w);
screen_draw_start_window(&ctx, w, data->ox, data->oy);
screen_draw_set_selection(&ctx, screen_write_start_window(&ctx, w);
data->selflag, data->selx, data->sely, for (i = 1; i < screen_size_y(s); i++) {
data->cx + data->ox, data->size + data->cy - data->oy); screen_write_move_cursor(&ctx, 0, i);
for (i = 1; i < screen_size_y(&w->screen); i++) { screen_write_delete_characters(&ctx, nx);
screen_draw_move_cursor(&ctx, 0, i);
screen_draw_delete_characters(&ctx, nx);
} }
for (i = 0; i < nx; i++) window_copy_write_columns(w, &ctx, screen_size_x(s) - nx, nx);
screen_draw_column(&ctx, screen_last_x(&w->screen) - i); window_copy_write_line(w, &ctx, 0);
window_copy_draw_position(w, &ctx); if (s->sel.flag) {
screen_draw_stop(&ctx); window_copy_update_selection(w);
window_copy_write_lines(w, &ctx, data->cy, 1);
}
screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
} }
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_draw_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i; u_int i;
if (data->ox < nx) if (data->ox < nx)
@ -492,72 +650,71 @@ window_copy_scroll_right(struct window *w, u_int nx)
if (nx == 0) if (nx == 0)
return; return;
data->ox -= nx; data->ox -= nx;
window_copy_update_selection(w);
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
screen_draw_set_selection(&ctx, for (i = 1; i < screen_size_y(s); i++) {
data->selflag, data->selx, data->sely, screen_write_move_cursor(&ctx, 0, i);
data->cx + data->ox, data->size + data->cy - data->oy); screen_write_insert_characters(&ctx, nx);
for (i = 1; i < screen_size_y(&w->screen); i++) {
screen_draw_move_cursor(&ctx, 0, i);
screen_draw_insert_characters(&ctx, nx);
} }
for (i = 0; i < nx; i++) window_copy_write_columns(w, &ctx, 0, nx);
screen_draw_column(&ctx, i); window_copy_write_line(w, &ctx, 0);
window_copy_draw_position(w, &ctx); if (s->sel.flag)
screen_draw_stop(&ctx); window_copy_write_lines(w, &ctx, data->cy, 1);
screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
} }
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_draw_ctx ctx; struct screen *s = &data->screen;
u_int i; struct screen_write_ctx ctx;
if (data->oy < ny) if (data->oy < ny)
ny = data->oy; ny = data->oy;
if (ny == 0) if (ny == 0)
return; return;
data->oy -= ny; data->oy -= ny;
window_copy_update_selection(w);
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
screen_draw_set_selection(&ctx, screen_write_move_cursor(&ctx, 0, 0);
data->selflag, data->selx, data->sely, screen_write_delete_lines(&ctx, ny);
data->cx + data->ox, data->size + data->cy - data->oy); window_copy_write_lines(w, &ctx, screen_size_y(s) - ny, ny);
screen_draw_move_cursor(&ctx, 0, 0); window_copy_write_line(w, &ctx, 0);
screen_draw_delete_lines(&ctx, ny); if (s->sel.flag && screen_size_y(s) > ny)
for (i = 0; i < ny; i++) window_copy_write_lines(w, &ctx, screen_size_y(s) - ny - 1, 1);
screen_draw_line(&ctx, screen_last_y(&w->screen) - i); screen_write_move_cursor(&ctx, data->cx, data->cy);
if (data->selflag) screen_write_stop(&ctx);
screen_draw_line(&ctx, screen_last_y(&w->screen) - ny);
window_copy_draw_position(w, &ctx);
screen_draw_stop(&ctx);
} }
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_draw_ctx ctx; struct screen *s = &data->screen;
u_int i; struct screen_write_ctx ctx;
if (ny > data->size) if (ny > w->base.hsize)
return; return;
if (data->oy > data->size - ny) if (data->oy > w->base.hsize - ny)
ny = data->size - data->oy; ny = w->base.hsize - data->oy;
if (ny == 0) if (ny == 0)
return; return;
data->oy += ny; data->oy += ny;
window_copy_update_selection(w);
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
screen_draw_set_selection(&ctx, screen_write_move_cursor(&ctx, 0, 0);
data->selflag, data->selx, data->sely, screen_write_insert_lines(&ctx, ny);
data->cx + data->ox, data->size + data->cy - data->oy); window_copy_write_lines(w, &ctx, 0, ny);
screen_draw_move_cursor(&ctx, 0, 0); if (s->sel.flag && screen_size_y(s) > ny)
screen_draw_insert_lines(&ctx, ny); window_copy_write_lines(w, &ctx, ny, 1);
for (i = 1; i < ny + 1; i++) else if (ny == 1) /* nuke position */
screen_draw_line(&ctx, i); window_copy_write_line(w, &ctx, 1);
window_copy_draw_position(w, &ctx); screen_write_move_cursor(&ctx, data->cx, data->cy);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }

View File

@ -1,4 +1,4 @@
/* $Id: window-more.c,v 1.5 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: window-more.c,v 1.6 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -23,25 +23,27 @@
#include "tmux.h" #include "tmux.h"
void window_more_init(struct window *); void window_more_init(struct window *);
void window_more_free(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 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_redraw_screen(struct window *);
void window_more_draw_line(struct window *, struct screen_draw_ctx *, u_int); void window_more_write_line(
struct window *, struct screen_write_ctx *, u_int);
void window_more_up_1(struct window *); void window_more_scroll_up(struct window *);
void window_more_down_1(struct window *); void window_more_scroll_down(struct window *);
const struct window_mode window_more_mode = { const struct window_mode window_more_mode = {
window_more_init, window_more_init,
window_more_free,
window_more_resize, window_more_resize,
window_more_draw,
window_more_key window_more_key
}; };
struct window_more_mode_data { struct window_more_mode_data {
struct screen screen;
ARRAY_DECL(, char *) list; ARRAY_DECL(, char *) list;
u_int top; u_int top;
}; };
@ -50,10 +52,25 @@ void
window_more_vadd(struct window *w, const char *fmt, va_list ap) window_more_vadd(struct window *w, const char *fmt, va_list ap)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
char *s; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
char *msg;
u_int size;
xvasprintf(&s, fmt, ap); xvasprintf(&msg, fmt, ap);
ARRAY_ADD(&data->list, s); ARRAY_ADD(&data->list, msg);
size = ARRAY_LENGTH(&data->list);
if (size == 0)
return;
size--;
if (size >= data->top && size <= data->top + screen_last_y(s)) {
screen_write_start_window(&ctx, w);
window_more_write_line(w, &ctx, size - data->top);
if (size != data->top)
window_more_write_line(w, &ctx, 0);
screen_write_stop(&ctx);
}
} }
void void
@ -70,170 +87,160 @@ void
window_more_init(struct window *w) window_more_init(struct window *w)
{ {
struct window_more_mode_data *data; struct window_more_mode_data *data;
struct screen *s;
w->modedata = data = xmalloc(sizeof *data); w->modedata = data = xmalloc(sizeof *data);
ARRAY_INIT(&data->list); ARRAY_INIT(&data->list);
data->top = 0; data->top = 0;
w->screen.mode |= MODE_BACKGROUND; s = &data->screen;
w->screen.mode &= ~MODE_BGCURSOR; screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base));
s->mode = 0;
w->screen = s;
} }
void void
window_more_resize(unused struct window *w, unused u_int sx, unused u_int sy) window_more_free(struct window *w)
{
}
void
window_more_draw_position(struct window *w, struct screen_draw_ctx *ctx)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
char *ptr, buf[32]; u_int i;
size_t len;
char *line;
len = xsnprintf( w->screen = &w->base;
buf, sizeof buf, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); screen_destroy(&data->screen);
if (len <= screen_size_x(ctx->s))
ptr = buf;
else {
ptr = buf + len - screen_size_x(ctx->s);
len -= len - screen_size_x(ctx->s);
}
screen_draw_move_cursor(ctx, 0, 0); for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
xfree(ARRAY_ITEM(&data->list, i));
ARRAY_FREE(&data->list);
if (data->top < ARRAY_LENGTH(&data->list)) { w->mode = NULL;
line = xstrdup(ARRAY_ITEM(&data->list, data->top)); xfree(w->modedata);
if (strlen(line) > screen_size_x(ctx->s) - len)
line[screen_size_x(ctx->s) - len] = '\0';
screen_draw_write_string(ctx, "%s", line);
xfree(line);
}
screen_draw_clear_line_to(ctx, screen_size_x(ctx->s) - len - 1);
screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0);
screen_draw_set_attributes(ctx, 0, status_colour);
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_resize(struct window *w, u_int sx, u_int sy)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
u_int p; struct screen *s = &data->screen;
screen_draw_move_cursor(ctx, 0, py); screen_resize(s, sx, sy);
screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); window_more_redraw_screen(w);
p = data->top + py;
if (p < ARRAY_LENGTH(&data->list))
screen_draw_write_string(ctx, "%s", ARRAY_ITEM(&data->list, p));
screen_draw_clear_line_to(ctx, screen_last_x(ctx->s));
}
void
window_more_draw(
struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny)
{
u_int i;
for (i = py; i < py + ny; i++) {
if (i == 0)
window_more_draw_position(w, ctx);
else
window_more_draw_line(w, ctx, i);
}
} }
void void
window_more_key(struct window *w, int key) window_more_key(struct window *w, int key)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
u_int top, sy, i; struct screen *s = &data->screen;
sy = screen_size_y(&w->screen);
top = data->top;
switch (key) { switch (key) {
case 'Q': case 'Q':
case 'q': case 'q':
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) window_more_free(w);
xfree(ARRAY_ITEM(&data->list, i));
ARRAY_FREE(&data->list);
w->mode = NULL;
xfree(w->modedata);
w->screen.mode &= ~MODE_BACKGROUND;
recalculate_sizes();
server_redraw_window(w); server_redraw_window(w);
return; break;
case 'k': case 'k':
case 'K': case 'K':
case KEYC_UP: case KEYC_UP:
window_more_up_1(w); window_more_scroll_up(w);
return; break;
case 'j': case 'j':
case 'J': case 'J':
case KEYC_DOWN: case KEYC_DOWN:
window_more_down_1(w); window_more_scroll_down(w);
return; break;
case '\025': /* C-u */ case '\025': /* C-u */
case KEYC_PPAGE: case KEYC_PPAGE:
if (data->top < sy) if (data->top < screen_size_y(s))
data->top = 0; data->top = 0;
else else
data->top -= sy; data->top -= screen_size_y(s);
window_more_redraw_screen(w);
break; break;
case '\006': /* C-f */ case '\006': /* C-f */
case KEYC_NPAGE: case KEYC_NPAGE:
if (data->top + sy > ARRAY_LENGTH(&data->list)) if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list))
data->top = ARRAY_LENGTH(&data->list); data->top = ARRAY_LENGTH(&data->list);
else else
data->top += sy; data->top += screen_size_y(s);
window_more_redraw_screen(w);
break; break;
} }
if (top != data->top)
server_redraw_window(w);
} }
void void
window_more_up_1(struct window *w) window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
{ {
struct window_more_mode_data *data = w->modedata; struct window_more_mode_data *data = w->modedata;
struct screen_draw_ctx ctx; struct screen *s = &data->screen;
char *msg;
size_t size;
if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour);
screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust(
ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
} else
size = 0;
screen_write_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
screen_write_move_cursor(ctx, 0, py);
if (data->top + py < ARRAY_LENGTH(&data->list)) {
msg = ARRAY_ITEM(&data->list, data->top + py);
screen_write_put_string(
ctx, "%.*s", (int) (screen_size_x(s) - size), msg);
}
while (s->cx < screen_size_x(s) - size)
screen_write_put_character(ctx, SCREEN_DEFDATA);
}
void
window_more_redraw_screen(struct window *w)
{
struct window_more_mode_data *data = w->modedata;
struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i;
screen_write_start_window(&ctx, w);
for (i = 0; i < screen_size_y(s); i++)
window_more_write_line(w, &ctx, i);
screen_write_stop(&ctx);
}
void
window_more_scroll_up(struct window *w)
{
struct window_more_mode_data *data = w->modedata;
struct screen_write_ctx ctx;
if (data->top == 0) if (data->top == 0)
return; return;
data->top--; data->top--;
screen_draw_start_window(&ctx, w, 0, 0); screen_write_start_window(&ctx, w);
screen_draw_move_cursor(&ctx, 0, 0); screen_write_move_cursor(&ctx, 0, 0);
screen_draw_insert_lines(&ctx, 1); screen_write_insert_lines(&ctx, 1);
window_more_draw_position(w, &ctx); window_more_write_line(w, &ctx, 0);
window_more_draw_line(w, &ctx, 1); window_more_write_line(w, &ctx, 1);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }
void void
window_more_down_1(struct window *w) window_more_scroll_down(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 = &data->screen;
struct screen_draw_ctx ctx; struct screen_write_ctx ctx;
if (data->top >= ARRAY_LENGTH(&data->list)) if (data->top >= ARRAY_LENGTH(&data->list))
return; return;
data->top++; data->top++;
screen_draw_start_window(&ctx, w, 0, 0); screen_write_start_window(&ctx, w);
screen_draw_move_cursor(&ctx, 0, 0); screen_write_move_cursor(&ctx, 0, 0);
screen_draw_delete_lines(&ctx, 1); screen_write_delete_lines(&ctx, 1);
window_more_draw_line(w, &ctx, screen_last_y(s)); window_more_write_line(w, &ctx, screen_last_y(s));
window_more_draw_position(w, &ctx); window_more_write_line(w, &ctx, 0);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }

View File

@ -1,4 +1,4 @@
/* $Id: window-scroll.c,v 1.14 2007-11-27 19:32:15 nicm Exp $ */ /* $Id: window-scroll.c,v 1.15 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -23,229 +23,253 @@
#include "tmux.h" #include "tmux.h"
void window_scroll_init(struct window *); void window_scroll_init(struct window *);
void window_scroll_free(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 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_redraw_screen(struct window *);
void window_scroll_write_line(
struct window *, struct screen_write_ctx *, u_int);
void window_scroll_write_column(
struct window *, struct screen_write_ctx *, u_int);
void window_scroll_up_1(struct window *); void window_scroll_scroll_up(struct window *);
void window_scroll_down_1(struct window *); void window_scroll_scroll_down(struct window *);
void window_scroll_left_1(struct window *); void window_scroll_scroll_left(struct window *);
void window_scroll_right_1(struct window *); void window_scroll_scroll_right(struct window *);
const struct window_mode window_scroll_mode = { const struct window_mode window_scroll_mode = {
window_scroll_init, window_scroll_init,
window_scroll_free,
window_scroll_resize, window_scroll_resize,
window_scroll_draw,
window_scroll_key window_scroll_key
}; };
struct window_scroll_mode_data { struct window_scroll_mode_data {
u_int ox; struct screen screen;
u_int oy;
u_int size; u_int ox;
u_int oy;
}; };
void void
window_scroll_init(struct window *w) window_scroll_init(struct window *w)
{ {
struct window_scroll_mode_data *data; struct window_scroll_mode_data *data;
struct screen *s;
struct screen_write_ctx ctx;
u_int i;
w->modedata = data = xmalloc(sizeof *data); w->modedata = data = xmalloc(sizeof *data);
data->ox = data->oy = 0; data->ox = 0;
data->size = w->screen.hsize; data->oy = 0;
w->screen.mode |= MODE_BACKGROUND; s = &data->screen;
w->screen.mode &= ~MODE_BGCURSOR; screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base));
s->mode = 0;
w->screen = s;
screen_write_start(&ctx, s, NULL, NULL);
for (i = 0; i < screen_size_y(s); i++)
window_scroll_write_line(w, &ctx, i);
screen_write_stop(&ctx);
} }
void void
window_scroll_resize(unused struct window *w, unused u_int sx, unused u_int sy) window_scroll_free(struct window *w)
{
}
void
window_scroll_draw_position(struct window *w, struct screen_draw_ctx *ctx)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
char *ptr, buf[32];
size_t len;
len = xsnprintf( w->screen = &w->base;
buf, sizeof buf, "[%u,%u/%u]", data->ox, data->oy, data->size); screen_destroy(&data->screen);
if (len <= screen_size_x(ctx->s))
ptr = buf; w->mode = NULL;
else { xfree(w->modedata);
ptr = buf + len - screen_size_x(ctx->s);
len -= len - screen_size_x(ctx->s);
}
screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len);
screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0);
screen_draw_set_attributes(ctx, 0, status_colour);
screen_draw_write_string(ctx, "%s", ptr);
} }
void void
window_scroll_draw( window_scroll_resize(struct window *w, u_int sx, u_int sy)
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 = &data->screen;
if (s->hsize != data->size) { screen_resize(s, sx, sy);
data->oy += s->hsize - data->size; screen_display_copy_area(&data->screen, &w->base,
data->size = s->hsize; 0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
}
screen_draw_set_offset(ctx, data->ox, data->oy);
if (py != 0)
screen_draw_lines(ctx, py, ny);
else {
if (ny > 1)
screen_draw_lines(ctx, py + 1, ny - 1);
window_scroll_draw_position(w, ctx);
}
} }
void void
window_scroll_key(struct window *w, int key) window_scroll_key(struct window *w, int key)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
u_int ox, oy, sx, sy; struct screen *s = &data->screen;
sx = screen_size_x(&w->screen);
sy = screen_size_y(&w->screen);
ox = data->ox;
oy = data->oy;
switch (key) { switch (key) {
case 'Q': case 'Q':
case 'q': case 'q':
w->mode = NULL; window_scroll_free(w);
xfree(w->modedata);
w->screen.mode &= ~MODE_BACKGROUND;
recalculate_sizes();
server_redraw_window(w); server_redraw_window(w);
return; break;
case 'h': case 'h':
case KEYC_LEFT: case KEYC_LEFT:
window_scroll_left_1(w); window_scroll_scroll_left(w);
return; break;
case 'l': case 'l':
case KEYC_RIGHT: case KEYC_RIGHT:
window_scroll_right_1(w); window_scroll_scroll_right(w);
return; break;
case 'k': case 'k':
case 'K': case 'K':
case KEYC_UP: case KEYC_UP:
window_scroll_up_1(w); window_scroll_scroll_up(w);
return; break;
case 'j': case 'j':
case 'J': case 'J':
case KEYC_DOWN: case KEYC_DOWN:
window_scroll_down_1(w); window_scroll_scroll_down(w);
return; break;
case '\025': /* C-u */ case '\025': /* C-u */
case KEYC_PPAGE: case KEYC_PPAGE:
if (data->oy + sy > data->size) if (data->oy + screen_size_y(s) > w->base.hsize)
data->oy = data->size; data->oy = w->base.hsize;
else else
data->oy += sy; data->oy += screen_size_y(s);
window_scroll_redraw_screen(w);
break; break;
case '\006': /* C-f */ case '\006': /* C-f */
case KEYC_NPAGE: case KEYC_NPAGE:
if (data->oy < sy) if (data->oy < screen_size_y(s))
data->oy = 0; data->oy = 0;
else else
data->oy -= sy; data->oy -= screen_size_y(s);
window_scroll_redraw_screen(w);
break; break;
} }
if (ox != data->ox || oy != data->oy)
server_redraw_window(w);
} }
void void
window_scroll_up_1(struct window *w) window_scroll_write_line(
struct window *w, struct screen_write_ctx *ctx, u_int py)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen_draw_ctx ctx; struct screen *s = &data->screen;
size_t size;
if (data->oy >= data->size) if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour);
screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust(
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
} else
size = 0;
screen_write_move_cursor(ctx, 0, py);
screen_write_copy_area(
ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
}
void
window_scroll_write_column(
struct window *w, struct screen_write_ctx *ctx, u_int px)
{
struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &data->screen;
screen_write_move_cursor(ctx, px, 0);
screen_write_copy_area(
ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
}
void
window_scroll_redraw_screen(struct window *w)
{
struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i;
screen_write_start_window(&ctx, w);
for (i = 0; i < screen_size_y(s); i++)
window_scroll_write_line(w, &ctx, i);
screen_write_stop(&ctx);
}
void
window_scroll_scroll_up(struct window *w)
{
struct window_scroll_mode_data *data = w->modedata;
struct screen_write_ctx ctx;
if (data->oy >= w->base.hsize)
return; return;
data->oy++; data->oy++;
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
screen_draw_move_cursor(&ctx, 0, 0); screen_write_move_cursor(&ctx, 0, 0);
screen_draw_insert_lines(&ctx, 1); screen_write_insert_lines(&ctx, 1);
window_scroll_draw_position(w, &ctx); window_scroll_write_line(w, &ctx, 0);
screen_draw_line(&ctx, 1); window_scroll_write_line(w, &ctx, 1);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }
void void
window_scroll_down_1(struct window *w) window_scroll_scroll_down(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen_draw_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
if (data->oy == 0) if (data->oy == 0)
return; return;
data->oy--; data->oy--;
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
screen_draw_move_cursor(&ctx, 0, 0); screen_write_move_cursor(&ctx, 0, 0);
screen_draw_delete_lines(&ctx, 1); screen_write_delete_lines(&ctx, 1);
screen_draw_line(&ctx, screen_last_y(&w->screen)); window_scroll_write_line(w, &ctx, screen_last_y(s));
window_scroll_draw_position(w, &ctx); window_scroll_write_line(w, &ctx, 0);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }
void void
window_scroll_right_1(struct window *w) window_scroll_scroll_right(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen_draw_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i; u_int i;
if (data->ox >= SHRT_MAX) if (data->ox >= SHRT_MAX)
return; return;
data->ox++; data->ox++;
screen_draw_start_window(&ctx, w, data->ox, data->oy); screen_write_start_window(&ctx, w);
for (i = 1; i < screen_size_y(&w->screen); i++) { for (i = 1; i < screen_size_y(s); i++) {
screen_draw_move_cursor(&ctx, 0, i); screen_write_move_cursor(&ctx, 0, i);
screen_draw_delete_characters(&ctx, 1); screen_write_delete_characters(&ctx, 1);
} }
screen_draw_column(&ctx, screen_last_x(&w->screen)); window_scroll_write_column(w, &ctx, screen_last_x(s));
window_scroll_draw_position(w, &ctx); window_scroll_write_line(w, &ctx, 0);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }
void void
window_scroll_left_1(struct window *w) window_scroll_scroll_left(struct window *w)
{ {
struct window_scroll_mode_data *data = w->modedata; struct window_scroll_mode_data *data = w->modedata;
struct screen_draw_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i; u_int i;
if (data->ox == 0) if (data->ox == 0)
return; return;
data->ox--; data->ox--;
screen_write_start_window(&ctx, w);
screen_draw_start_window(&ctx, w, data->ox, data->oy); for (i = 1; i < screen_size_y(s); i++) {
for (i = 1; i < screen_size_y(&w->screen); i++) { screen_write_move_cursor(&ctx, 0, i);
screen_draw_move_cursor(&ctx, 0, i); screen_write_insert_characters(&ctx, 1);
screen_draw_insert_characters(&ctx, 1);
} }
screen_draw_column(&ctx, 0); window_scroll_write_column(w, &ctx, 0);
window_scroll_draw_position(w, &ctx); window_scroll_write_line(w, &ctx, 0);
screen_draw_stop(&ctx); screen_write_stop(&ctx);
} }

View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.32 2007-11-27 19:23:34 nicm Exp $ */ /* $Id: window.c,v 1.33 2007-12-06 09:46:23 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -90,7 +90,7 @@ winlink_next_index(struct winlinks *wwl)
if (winlink_find_by_index(wwl, i) == NULL) if (winlink_find_by_index(wwl, i) == NULL)
return (i); return (i);
} }
fatalx("no free indexes"); fatalx("no free indexes");
} }
@ -136,7 +136,7 @@ struct winlink *
winlink_next(unused struct winlinks *wwl, struct winlink *wl) winlink_next(unused struct winlinks *wwl, struct winlink *wl)
{ {
return (RB_NEXT(winlinks, wwl, wl)); return (RB_NEXT(winlinks, wwl, wl));
} }
struct winlink * struct winlink *
winlink_previous(struct winlinks *wwl, struct winlink *wl) winlink_previous(struct winlinks *wwl, struct winlink *wl)
@ -153,7 +153,7 @@ winlink_previous(struct winlinks *wwl, struct winlink *wl)
if (wl == NULL) if (wl == NULL)
return (NULL); return (NULL);
return (wk); return (wk);
} }
struct window * struct window *
window_create( window_create(
@ -189,14 +189,15 @@ window_create(
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
w = xmalloc(sizeof *w); w = xmalloc(sizeof *w);
w->fd = fd; w->fd = fd;
w->in = buffer_create(BUFSIZ); w->in = buffer_create(BUFSIZ);
w->out = buffer_create(BUFSIZ); w->out = buffer_create(BUFSIZ);
w->mode = NULL; w->mode = NULL;
screen_create(&w->screen, sx, sy); screen_create(&w->base, sx, sy);
w->screen = &w->base;
input_init(w); input_init(w);
if (name == NULL) { if (name == NULL) {
@ -238,12 +239,14 @@ window_destroy(struct window *w)
break; break;
} }
ARRAY_REMOVE(&windows, i); ARRAY_REMOVE(&windows, i);
close(w->fd); close(w->fd);
input_free(w); input_free(w);
screen_destroy(&w->screen); screen_destroy(&w->base);
if (w->mode != NULL)
w->mode->free(w);
buffer_destroy(w->in); buffer_destroy(w->in);
buffer_destroy(w->out); buffer_destroy(w->out);
@ -257,16 +260,16 @@ window_resize(struct window *w, u_int sx, u_int sy)
{ {
struct winsize ws; struct winsize ws;
if (sx == screen_size_x(&w->screen) && sy == screen_size_y(&w->screen)) if (sx == screen_size_x(&w->base) && sy == screen_size_y(&w->base))
return (-1); return (-1);
memset(&ws, 0, sizeof ws); memset(&ws, 0, sizeof ws);
ws.ws_col = sx; ws.ws_col = sx;
ws.ws_row = sy; ws.ws_row = sy;
screen_resize(&w->base, sx, sy);
if (w->mode != NULL) if (w->mode != NULL)
w->mode->resize(w, sx, sy); w->mode->resize(w, sx, sy);
screen_resize(&w->screen, sx, sy);
if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1) if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1)
fatal("ioctl failed"); fatal("ioctl failed");
@ -279,20 +282,11 @@ window_parse(struct window *w)
input_parse(w); input_parse(w);
} }
void
window_draw(struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny)
{
if (w->mode != NULL)
w->mode->draw(w, ctx, py, ny);
else
screen_draw_lines(ctx, py, ny);
}
void void
window_key(struct window *w, int key) 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, key); input_key(w, key);
} }