From 9a6e47cfa8b7ebac8bebc7c2027fd72bee9d38ab Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 21 Nov 2007 13:11:41 +0000 Subject: [PATCH] Initial history support. --- CHANGES | 9 ++- Makefile | 5 +- TODO | 4 ++ cmd-kill-session.c | 4 +- cmd-list-windows.c | 7 +- cmd-scroll-mode.c | 55 +++++++++++++++ cmd-send-prefix.c | 5 +- cmd.c | 3 +- input-keys.c | 4 +- input.c | 120 ++++++++++++++++++++----------- key-bindings.c | 5 +- resize.c | 7 +- screen-display.c | 46 +++++++++--- screen.c | 171 ++++++++++++++++++++++----------------------- server-fn.c | 14 ++-- server-msg.c | 14 ++-- server.c | 4 +- status.c | 4 +- tmux.h | 45 ++++++++---- window-scroll.c | 122 ++++++++++++++++++++++++++++++++ window.c | 30 +++++++- 21 files changed, 491 insertions(+), 187 deletions(-) create mode 100644 cmd-scroll-mode.c create mode 100644 window-scroll.c diff --git a/CHANGES b/CHANGES index a4001560..9eaeba19 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +21 November 2007 + +* Initial support for scroll history. = to enter scrolling mode, and then + vi keys or up/down/pgup/pgdown to navigate. Q to exit. No horizontal history + yet (need per-line sizes) and a few kinks to be worked out (resizing while in + history mode will probably cause trouble). + 20 November 2007 * Fix format string error with "must specify a client" message. Also @@ -233,4 +240,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.75 2007-11-20 18:11:37 nicm Exp $ +$Id: CHANGES,v 1.76 2007-11-21 13:11:41 nicm Exp $ diff --git a/Makefile b/Makefile index 8bbc2ed6..9d6e04e4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.44 2007-11-20 21:42:28 nicm Exp $ +# $Id: Makefile,v 1.45 2007-11-21 13:11:41 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -26,7 +26,8 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \ cmd-link-window.c cmd-unlink-window.c cmd-next-window.c \ cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ - cmd-switch-client.c cmd-has-session.c + cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c \ + window-scroll.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index 7ecb806c..a6522116 100644 --- a/TODO +++ b/TODO @@ -65,10 +65,14 @@ - session specification is all over the place. some things use -s before cmd, some -s after, some no -s, there are various uses of -n. the differences are sort of logical, but confusing. needs rethought +- XXX should -i for win idx be before cmd too?? - bind non prefix keys (useful for shift-pageup for scrollback, when we have scrollback) +- for scrollback (?) or copy/paste, modal key/display handling (key/draw + through function pointers in screen). also move ? etc to that too - stuff like rename would be nice to be able to do in-client like screen, if it could be implemented in a non-icky way +- there is to much redrawing. use flags? (there was a problem with this idea..?) -- For 0.2 -------------------------------------------------------------------- - copy and paste diff --git a/cmd-kill-session.c b/cmd-kill-session.c index b7853810..e4addc87 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-kill-session.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-kill-session.c,v 1.4 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -58,6 +58,6 @@ cmd_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx) session_destroy(ctx->session); - if (!(ctx->flags & CMD_KEY)) + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-list-windows.c b/cmd-list-windows.c index c7bd1716..c2a5e09a 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-windows.c,v 1.9 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: cmd-list-windows.c,v 1.10 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -47,9 +47,10 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx) RB_FOREACH(wl, winlinks, &ctx->session->windows) { w = wl->window; - ctx->print(ctx, "%d: %s \"%s\" (%s) [%ux%u]", + ctx->print(ctx, "%d: %s \"%s\" (%s) [%ux%u] [history %u]", wl->idx, w->name, w->screen.title, ttyname(w->fd), - screen_size_x(&w->screen), screen_size_y(&w->screen)); + screen_size_x(&w->screen), screen_size_y(&w->screen), + w->screen.hsize); } if (ctx->cmdclient != NULL) diff --git a/cmd-scroll-mode.c b/cmd-scroll-mode.c new file mode 100644 index 00000000..3bc98825 --- /dev/null +++ b/cmd-scroll-mode.c @@ -0,0 +1,55 @@ +/* $Id: cmd-scroll-mode.c,v 1.1 2007-11-21 13:11:41 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "tmux.h" + +/* + * Enter scroll mode. Only valid when bound to a key. + */ + +void cmd_scroll_mode_exec(void *, struct cmd_ctx *); + +const struct cmd_entry cmd_scroll_mode_entry = { + "scroll-mode", "scroll", "", + CMD_NOCLIENT, + NULL, + cmd_scroll_mode_exec, + NULL, + NULL, + NULL +}; + +void +cmd_scroll_mode_exec(unused void *ptr, struct cmd_ctx *ctx) +{ + struct window *w = ctx->session->curw->window; + + if (ctx->flags & CMD_KEY) { + w->mode = &window_scroll_mode; + w->mode->init(w); + server_redraw_window_all(w); + } + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index 1dc9ae02..3d556675 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-prefix.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-send-prefix.c,v 1.6 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -42,8 +42,7 @@ const struct cmd_entry cmd_send_prefix_entry = { void cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx) { - input_translate_key( - ctx->client->session->curw->window->out, prefix_key); + window_key(ctx->client->session->curw->window, prefix_key); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd.c b/cmd.c index 0be6aebb..91c41103 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.29 2007-11-16 21:31:03 nicm Exp $ */ +/* $Id: cmd.c,v 1.30 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -43,6 +43,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_refresh_client_entry, &cmd_rename_session_entry, &cmd_rename_window_entry, + &cmd_scroll_mode_entry, &cmd_select_window_entry, &cmd_send_prefix_entry, &cmd_set_option_entry, diff --git a/input-keys.c b/input-keys.c index d143494b..1d11893f 100644 --- a/input-keys.c +++ b/input-keys.c @@ -1,4 +1,4 @@ -/* $Id: input-keys.c,v 1.2 2007-10-19 11:10:35 nicm Exp $ */ +/* $Id: input-keys.c,v 1.3 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -55,7 +55,7 @@ struct { /* Translate a key code from client into an output key sequence. */ void -input_translate_key(struct buffer *b, int key) +input_key(struct buffer *b, int key) { u_int i; diff --git a/input.c b/input.c index f9061aab..4b8ec5f0 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.33 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: input.c,v 1.34 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -308,12 +308,12 @@ input_state_sequence_first(u_char ch, struct input_ctx *ictx) ARRAY_CLEAR(&ictx->args); if (INPUT_PARAMETER(ch)) { + input_new_argument(ictx); /* XXX extraneous arg if priv */ if (ch >= 0x3c && ch <= 0x3f) { /* Private control sequence. */ ictx->private = ch; return (input_state_sequence_next); } - input_new_argument(ictx); } /* Pass character on directly. */ @@ -373,8 +373,10 @@ input_handle_character(u_char ch, struct input_ctx *ictx) log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch); if (s->cx == screen_size_x(s)) { - input_store8(ictx->b, '\r'); - input_store8(ictx->b, '\n'); + if (!screen_hidden(s)) { + input_store8(ictx->b, '\r'); + input_store8(ictx->b, '\n'); + } s->cx = 0; screen_display_cursor_down(s); @@ -382,7 +384,8 @@ input_handle_character(u_char ch, struct input_ctx *ictx) return; screen_display_cursor_set(s, ch); - input_store8(ictx->b, ch); + if (!screen_hidden(s)) + input_store8(ictx->b, ch); s->cx++; } @@ -416,14 +419,17 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) s->cx = 0; screen_display_cursor_down(s); } - input_store_two( - ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + if (!screen_hidden(s)) { + input_store_two( + ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + } return; default: log_debug("unknown c0: %hhu", ch); return; } - input_store8(ictx->b, ch); + if (!screen_hidden(s)) + input_store8(ictx->b, ch); } void @@ -436,7 +442,8 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) switch (ch) { case 'M': /* RI */ screen_display_cursor_up(s); - input_store_zero(ictx->b, CODE_REVERSEINDEX); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_REVERSEINDEX); break; default: log_debug("unknown c1: %hhu", ch); @@ -453,10 +460,12 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx) switch (ch) { case '=': /* DECKPAM */ - input_store_zero(ictx->b, CODE_KKEYPADON); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_KKEYPADON); break; case '>': /* DECKPNM*/ - input_store_zero(ictx->b, CODE_KKEYPADOFF); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_KKEYPADOFF); break; case '7': /* DECSC */ s->saved_cx = s->cx; @@ -472,12 +481,14 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx) s->cy = s->saved_cy; s->attr = s->saved_attr; s->colr = s->saved_colr; - input_store_two( - ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); - input_store_two(ictx->b, CODE_SCROLLREGION, - s->rupper + 1, s->rlower + 1); - input_store_two( - ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + if (!screen_hidden(s)) { + input_store_two( + ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); + input_store_two(ictx->b, CODE_SCROLLREGION, + s->rupper + 1, s->rlower + 1); + input_store_two( + ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); + } break; default: log_debug("unknown p2: %hhu", ch); @@ -564,7 +575,8 @@ input_handle_sequence_cuu(struct input_ctx *ictx) } s->cy -= n; - input_store_one(ictx->b, CODE_CURSORUP, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_CURSORUP, n); } void @@ -586,7 +598,8 @@ input_handle_sequence_cud(struct input_ctx *ictx) input_limit(n, 1, screen_last_y(s) - s->cy); s->cy += n; - input_store_one(ictx->b, CODE_CURSORDOWN, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_CURSORDOWN, n); } void @@ -608,7 +621,8 @@ input_handle_sequence_cuf(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); s->cx += n; - input_store_one(ictx->b, CODE_CURSORRIGHT, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_CURSORRIGHT, n); } void @@ -631,7 +645,8 @@ input_handle_sequence_cub(struct input_ctx *ictx) } s->cx -= n; - input_store_one(ictx->b, CODE_CURSORLEFT, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_CURSORLEFT, n); } void @@ -653,7 +668,8 @@ input_handle_sequence_dch(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); screen_display_delete_characters(s, s->cx, s->cy, n); - input_store_one(ictx->b, CODE_DELETECHARACTER, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_DELETECHARACTER, n); } void @@ -678,7 +694,8 @@ input_handle_sequence_dl(struct input_ctx *ictx) screen_display_delete_lines(s, s->cy, n); else screen_display_delete_lines_region(s, s->cy, n); - input_store_one(ictx->b, CODE_DELETELINE, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_DELETELINE, n); } void @@ -700,7 +717,8 @@ input_handle_sequence_ich(struct input_ctx *ictx) input_limit(n, 1, screen_last_x(s) - s->cx); screen_display_insert_characters(s, s->cx, s->cy, n); - input_store_one(ictx->b, CODE_INSERTCHARACTER, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_INSERTCHARACTER, n); } void @@ -725,7 +743,8 @@ input_handle_sequence_il(struct input_ctx *ictx) screen_display_insert_lines(s, s->cy, n); else screen_display_insert_lines_region(s, s->cy, n); - input_store_one(ictx->b, CODE_INSERTLINE, n); + if (!screen_hidden(s)) + input_store_one(ictx->b, CODE_INSERTLINE, n); } void @@ -747,7 +766,8 @@ input_handle_sequence_vpa(struct input_ctx *ictx) input_limit(n, 1, screen_size_y(s)); s->cy = n - 1; - input_store_two(ictx->b, CODE_CURSORMOVE, n, s->cx + 1); + if (!screen_hidden(s)) + input_store_two(ictx->b, CODE_CURSORMOVE, n, s->cx + 1); } void @@ -769,7 +789,8 @@ input_handle_sequence_hpa(struct input_ctx *ictx) input_limit(n, 1, screen_size_x(s)); s->cx = n - 1; - input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, n); + if (!screen_hidden(s)) + input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, n); } void @@ -793,7 +814,8 @@ input_handle_sequence_cup(struct input_ctx *ictx) s->cx = m - 1; s->cy = n - 1; - input_store_two(ictx->b, CODE_CURSORMOVE, n, m); + if (!screen_hidden(s)) + input_store_two(ictx->b, CODE_CURSORMOVE, n, m); } void @@ -819,6 +841,8 @@ input_handle_sequence_ed(struct input_ctx *ictx) screen_display_fill_cursor_eos( s, SCREEN_DEFDATA, s->attr, s->colr); + if (!screen_hidden(s)) + break; input_store_zero(ictx->b, CODE_CLEARLINE); for (i = s->cy + 1; i < screen_size_y(s); i++) { input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); @@ -830,7 +854,9 @@ input_handle_sequence_ed(struct input_ctx *ictx) case 2: screen_display_fill_lines( s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr); - + + if (!screen_hidden(s)) + break; for (i = 0; i < screen_size_y(s); i++) { input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); input_store_zero(ictx->b, CODE_CLEARLINE); @@ -862,17 +888,23 @@ input_handle_sequence_el(struct input_ctx *ictx) case 0: screen_display_fill_cursor_eol( s, SCREEN_DEFDATA, s->attr, s->colr); - input_store_zero(ictx->b, CODE_CLEARENDOFLINE); + + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_CLEARENDOFLINE); break; case 1: screen_display_fill_cursor_bol( s, SCREEN_DEFDATA, s->attr, s->colr); - input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE); + + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE); break; case 2: screen_display_fill_line( s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); - input_store_zero(ictx->b, CODE_CLEARLINE); + + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_CLEARLINE); break; } } @@ -892,11 +924,13 @@ input_handle_sequence_sm(struct input_ctx *ictx) switch (n) { case 1: /* GATM */ s->mode |= MODE_KCURSOR; - input_store_zero(ictx->b, CODE_KCURSORON); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_KCURSORON); break; case 25: /* TCEM */ s->mode |= MODE_CURSOR; - input_store_zero(ictx->b, CODE_CURSORON); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_CURSORON); break; default: log_debug("unknown SM [%hhu]: %u", ictx->private, n); @@ -906,7 +940,8 @@ input_handle_sequence_sm(struct input_ctx *ictx) switch (n) { case 4: /* IRM */ s->mode |= MODE_INSERT; - input_store_zero(ictx->b, CODE_INSERTON); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_INSERTON); break; case 34: /* Cursor high visibility not supported. */ @@ -933,11 +968,13 @@ input_handle_sequence_rm(struct input_ctx *ictx) switch (n) { case 1: /* GATM */ s->mode &= ~MODE_KCURSOR; - input_store_zero(ictx->b, CODE_KCURSOROFF); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_KCURSOROFF); break; case 25: /* TCEM */ s->mode &= ~MODE_CURSOR; - input_store_zero(ictx->b, CODE_CURSOROFF); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_CURSOROFF); break; default: log_debug("unknown RM [%hhu]: %u", ictx->private, n); @@ -947,7 +984,8 @@ input_handle_sequence_rm(struct input_ctx *ictx) switch (n) { case 4: /* IRM */ s->mode &= ~MODE_INSERT; - input_store_zero(ictx->b, CODE_INSERTOFF); + if (!screen_hidden(s)) + input_store_zero(ictx->b, CODE_INSERTOFF); break; case 34: /* Cursor high visibility not supported. */ @@ -1021,7 +1059,8 @@ input_handle_sequence_decstbm(struct input_ctx *ictx) s->rupper = n - 1; s->rlower = m - 1; - input_store_two(ictx->b, CODE_SCROLLREGION, n, m); + if (!screen_hidden(s)) + input_store_two(ictx->b, CODE_SCROLLREGION, n, m); } void @@ -1105,7 +1144,8 @@ input_handle_sequence_sgr(struct input_ctx *ictx) } } } - input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); + if (!screen_hidden(s)) + input_store_two(ictx->b, CODE_ATTRIBUTES, s->attr, s->colr); } void diff --git a/key-bindings.c b/key-bindings.c index 0af94f8d..f17f5c86 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.17 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.18 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -108,6 +108,7 @@ key_bindings_init(void) { 'R', &cmd_refresh_client_entry, NULL }, { 'r', &cmd_refresh_client_entry, NULL }, { '&', &cmd_kill_window_entry, NULL }, + { '=', &cmd_scroll_mode_entry, NULL }, { META, &cmd_send_prefix_entry, NULL }, }; u_int i; @@ -176,7 +177,7 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) size = BUFFER_USED(c->out); if (line == 2 * sy || !(c->flags & CLIENT_HOLD)) { - input_store_zero(c->out, CODE_CURSOROFF); + input_store_zero(c->out, CODE_CURSOROFF); for (i = 0; i < sy; i++) { input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1); input_store_zero(c->out, CODE_CLEARLINE); diff --git a/resize.c b/resize.c index 2e9380c3..a48f5c0a 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.5 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: resize.c,v 1.6 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -104,8 +104,11 @@ recalculate_sizes(void) ssy = s->sy; } } - if (ssx == UINT_MAX || ssy == UINT_MAX) + if (ssx == UINT_MAX || ssy == UINT_MAX) { + w->screen.mode |= MODE_HIDDEN; continue; + } + w->screen.mode &= ~MODE_HIDDEN; if (screen_size_x(&w->screen) == ssx && screen_size_y(&w->screen) == ssy) diff --git a/screen-display.c b/screen-display.c index 5f2790aa..e11c6aaa 100644 --- a/screen-display.c +++ b/screen-display.c @@ -1,4 +1,4 @@ -/* $Id: screen-display.c,v 1.1 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: screen-display.c,v 1.2 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -168,6 +168,36 @@ screen_display_cursor_down(struct screen *s) void screen_display_scroll_region_up(struct screen *s) { + u_int sy; + + /* + * If the region is the entire screen, this is easy-peasy. Allocate + * a new line and adjust the history size. + * XXX1 should this be done somewhere else? + */ + if (s->rupper == 0 && s->rlower == screen_last_y(s)) { + sy = screen_size_y(s) + s->hsize; + + if (s->hsize == s->hlimit) { + /* + * If the limit is hit, shift the whole thing up. + * XXX this is inefficient, is there a better way? + */ + screen_move_lines(s, 0, 1, sy - 1); + } else { + s->hsize++; + + s->grid_data = xrealloc( + s->grid_data, sy + 1, sizeof *s->grid_data); + s->grid_attr = xrealloc( + s->grid_attr, sy + 1, sizeof *s->grid_attr); + s->grid_colr = xrealloc( + s->grid_colr, sy + 1, sizeof *s->grid_colr); + } + screen_display_make_lines(s, screen_last_y(s), 1); + return; + } + /* * Scroll scrolling region up: * - delete rupper @@ -189,8 +219,6 @@ screen_display_scroll_region_up(struct screen *s) } screen_display_make_lines(s, s->rlower, 1); - screen_display_fill_lines( - s, s->rlower, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } /* Scroll region down. */ @@ -218,8 +246,6 @@ screen_display_scroll_region_down(struct screen *s) } screen_display_make_lines(s, s->rupper, 1); - screen_display_fill_lines( - s, s->rupper, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } /* Insert lines. */ @@ -368,15 +394,14 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) { u_int mx; - px = screen_x(s, px); - py = screen_y(s, py); - if (!screen_in_x(s, px) || !screen_in_y(s, py)) fatalx("bad value"); if (px + nx > screen_last_x(s)) nx = screen_last_x(s) - px; + py = screen_y(s, py); + /* * Inserting a range of nx at px. * @@ -401,15 +426,14 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) { u_int mx; - px = screen_x(s, px); - py = screen_y(s, py); - if (!screen_in_x(s, px) || !screen_in_y(s, py)) fatalx("bad value"); if (px + nx > screen_last_x(s)) nx = screen_last_x(s) - px; + py = screen_y(s, py); + /* * Deleting the range from px to px + nx. * diff --git a/screen.c b/screen.c index 06f3b99b..34051da0 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.27 2007-11-20 21:45:53 nicm Exp $ */ +/* $Id: screen.c,v 1.28 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -23,9 +23,7 @@ #include "tmux.h" /* - * Virtual screen and basic terminal emulator. - * - * XXX Much of this file sucks. + * Virtual screen. */ /* Colour to string. */ @@ -92,8 +90,8 @@ screen_create(struct screen *s, u_int dx, u_int dy) s->rupper = 0; s->rlower = s->dy - 1; - s->ysize = dy; - s->ylimit = SHRT_MAX; + s->hsize = 0; + s->hlimit = SHRT_MAX; s->attr = SCREEN_DEFATTR; s->colr = SCREEN_DEFCOLR; @@ -111,10 +109,7 @@ screen_create(struct screen *s, u_int dx, u_int dy) void screen_resize(struct screen *s, u_int sx, u_int sy) { - u_int i, ox, oy, ny; - - if (sx == s->dx && sy == s->dy) - return; + u_int i, ox, oy, ny, my; if (sx < 1) sx = 1; @@ -123,83 +118,79 @@ screen_resize(struct screen *s, u_int sx, u_int sy) ox = s->dx; oy = s->dy; + if (sx == ox && sy == oy) + return; - log_debug("resizing screen (%u, %u) -> (%u, %u)", ox, oy, sx, sy); - - s->dx = sx; - s->dy = sy; - - s->rupper = 0; - s->rlower = s->dy - 1; - - s->ysize = sy; - - if (sy < oy) { - ny = oy - sy; - if (ny > s->cy) - ny = s->cy; - - if (ny != 0) { - log_debug("removing %u lines from top", ny); - for (i = 0; i < ny; i++) { - log_debug("freeing line %u", i); - xfree(s->grid_data[i]); - xfree(s->grid_attr[i]); - xfree(s->grid_colr[i]); - } - memmove(s->grid_data, s->grid_data + ny, - (oy - ny) * (sizeof *s->grid_data)); - memmove(s->grid_attr, s->grid_attr + ny, - (oy - ny) * (sizeof *s->grid_attr)); - memmove(s->grid_colr, s->grid_colr + ny, - (oy - ny) * (sizeof *s->grid_colr)); - s->cy -= ny; - } - if (ny < oy - sy) { - log_debug( - "removing %u lines from bottom", oy - sy - ny); - for (i = sy; i < oy - ny; i++) { - log_debug("freeing line %u", i); - xfree(s->grid_data[i]); - xfree(s->grid_attr[i]); - xfree(s->grid_colr[i]); - } - if (s->cy >= sy) - s->cy = sy - 1; - } - } - if (sy != oy) { - s->grid_data = xrealloc(s->grid_data, sy, sizeof *s->grid_data); - s->grid_attr = xrealloc(s->grid_attr, sy, sizeof *s->grid_attr); - s->grid_colr = xrealloc(s->grid_colr, sy, sizeof *s->grid_colr); - } - if (sy > oy) { - for (i = oy; i < sy; i++) { - log_debug("allocating line %u", i); - s->grid_data[i] = xmalloc(sx); - s->grid_attr[i] = xmalloc(sx); - s->grid_colr[i] = xmalloc(sx); - screen_display_fill_line(s, i, - SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); - } - sy = oy; - } - + /* + * X dimension. + */ if (sx != ox) { - for (i = 0; i < sy; i++) { - log_debug("adjusting line %u to %u", i, sx); + /* Resize all lines including history. */ + /* XXX need per-line sizes! */ + for (i = 0; i < s->hsize + oy; i++) { s->grid_data[i] = xrealloc(s->grid_data[i], sx, 1); s->grid_attr[i] = xrealloc(s->grid_attr[i], sx, 1); s->grid_colr[i] = xrealloc(s->grid_colr[i], sx, 1); if (sx > ox) { - screen_display_fill_cells(s, ox, i, s->dx - ox, + screen_fill_cells(s, ox, i, sx - ox, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } } if (s->cx >= sx) s->cx = sx - 1; + s->dx = sx; } + + /* + * Y dimension. + */ + if (sy == oy) + return; + + /* Size decreasing. */ + if (sy < oy) { + ny = oy - sy; + if (s->cy != 0) { + /* + * The cursor is not at the start. Try to remove as + * many lines as possible from the top. + */ + my = s->cy; + if (my > ny) + my = ny; + + screen_display_free_lines(s, 0, my); + screen_display_move_lines(s, 0, my, oy - my); + + s->cy -= my; + oy -= my; + } + + ny = oy - sy; + if (ny > 0) { + /* + * Remove any remaining lines from the bottom. + */ + screen_display_free_lines(s, oy, ny); + if (s->cy >= sy) + s->cy = sy - 1; + } + } + + /* Resize line arrays. */ + ny = s->hsize + sy; + s->grid_data = xrealloc(s->grid_data, ny, sizeof *s->grid_data); + s->grid_attr = xrealloc(s->grid_attr, ny, sizeof *s->grid_attr); + s->grid_colr = xrealloc(s->grid_colr, ny, sizeof *s->grid_colr); + s->dy = sy; + + /* Size increasing. */ + if (sy > oy) + screen_display_make_lines(s, oy, sy - oy); + + s->rupper = 0; + s->rlower = s->dy - 1; } /* Destroy a screen. */ @@ -214,13 +205,10 @@ screen_destroy(struct screen *s) /* Draw a set of lines on the screen. */ void -screen_draw(struct screen *s, struct buffer *b, u_int uy, u_int ly) +screen_draw(struct screen *s, struct buffer *b, u_int py, u_int ny, u_int off) { - u_char attr, colr; - u_int i, j; - - if (uy > s->dy - 1 || ly > s->dy - 1 || ly < uy) - fatalx("bad range"); + u_char attr, colr; + u_int i, j, base; /* XXX. This is naive and rough right now. */ attr = 0; @@ -231,20 +219,27 @@ screen_draw(struct screen *s, struct buffer *b, u_int uy, u_int ly) input_store_zero(b, CODE_CURSOROFF); input_store_two(b, CODE_ATTRIBUTES, attr, colr); - for (j = uy; j <= ly; j++) { + base = screen_y(s, 0); + if (off > base) + base = 0; + else + base -= off; + + for (j = py; j < py + ny; j++) { input_store_two(b, CODE_CURSORMOVE, j + 1, 1); for (i = 0; i <= screen_last_x(s); i++) { - if (s->grid_attr[j][i] != attr || - s->grid_colr[j][i] != colr) { + if (s->grid_attr[base + j][i] != attr || + s->grid_colr[base + j][i] != colr) { input_store_two(b, CODE_ATTRIBUTES, - s->grid_attr[j][i], s->grid_colr[j][i]); - attr = s->grid_attr[j][i]; - colr = s->grid_colr[j][i]; + s->grid_attr[base + j][i], + s->grid_colr[base + j][i]); + attr = s->grid_attr[base + j][i]; + colr = s->grid_colr[base + j][i]; } - input_store8(b, s->grid_data[j][i]); + input_store8(b, s->grid_data[base + j][i]); } - } + } input_store_two(b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); input_store_two(b, CODE_ATTRIBUTES, s->attr, s->colr); diff --git a/server-fn.c b/server-fn.c index 40a35400..af651a81 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.26 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: server-fn.c,v 1.27 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -192,7 +192,7 @@ server_clear_client(struct client *c) void server_redraw_client(struct client *c) { - struct screen *s = &c->session->curw->window->screen; + struct window *w = c->session->curw->window; struct hdr hdr; size_t size; @@ -200,10 +200,10 @@ server_redraw_client(struct client *c) buffer_add(c->out, sizeof hdr); size = BUFFER_USED(c->out); - screen_draw(s, c->out, 0, screen_last_y(s)); + window_draw(w, c->out, 0, screen_size_y(&w->screen)); size = BUFFER_USED(c->out) - size; - log_debug("redrawing screen, %zu bytes", size); + log_debug("redrawing window, %zu bytes", size); if (size != 0) { hdr.type = MSG_DATA; hdr.size = size; @@ -330,7 +330,7 @@ server_status_window_all(struct window *w) void printflike2 server_write_message(struct client *c, const char *fmt, ...) { - struct screen *s = &c->session->curw->window->screen; + struct window *w = c->session->curw->window; struct hdr hdr; va_list ap; char *msg; @@ -355,7 +355,7 @@ server_write_message(struct client *c, const char *fmt, ...) xfree(msg); size = BUFFER_USED(c->out) - size; - hdr.type = MSG_DATA; + hdr.type = MSG_DATA; hdr.size = size; memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); @@ -368,7 +368,7 @@ server_write_message(struct client *c, const char *fmt, ...) size = BUFFER_USED(c->out); if (status_lines == 0) { - screen_draw(s, c->out, c->sy - 1, c->sy - 1); + window_draw(w, c->out, screen_last_y(&w->screen), 1); } else status_write(c); diff --git a/server-msg.c b/server-msg.c index 329bfb3e..d75f23ba 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.33 2007-11-20 18:11:37 nicm Exp $ */ +/* $Id: server-msg.c,v 1.34 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -236,8 +236,9 @@ server_msg_fn_resize(struct hdr *hdr, struct client *c) int server_msg_fn_keys(struct hdr *hdr, struct client *c) { - int key; - size_t size; + struct window *w = c->session->curw->window; + int key; + size_t size; if (hdr->size & 0x1) fatalx("bad MSG_KEYS size"); @@ -258,10 +259,11 @@ server_msg_fn_keys(struct hdr *hdr, struct client *c) continue; } - if (key == prefix_key) + if (key == prefix_key) { c->flags |= CLIENT_PREFIX; - else - input_translate_key(c->session->curw->window->out, key); + continue; + } + window_key(w, key); } return (0); diff --git a/server.c b/server.c index 6a5977fb..f71d6d1d 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.38 2007-11-12 15:12:08 nicm Exp $ */ +/* $Id: server.c,v 1.39 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -346,7 +346,7 @@ server_handle_window(struct window *w) u_int i; b = buffer_create(BUFSIZ); - input_parse(w, b); + window_parse(w, b); if (BUFFER_USED(b) != 0) { server_write_window_cur( w, MSG_DATA, BUFFER_OUT(b), BUFFER_USED(b)); diff --git a/status.c b/status.c index 90a2363e..e1bb046a 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.9 2007-11-20 18:11:37 nicm Exp $ */ +/* $Id: status.c,v 1.10 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -57,7 +57,7 @@ status_write(struct client *c) input_store_two(b, CODE_ATTRIBUTES, s->attr, s->colr); input_store_two(b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); - if (s->mode & MODE_CURSOR) + if (!(s->mode & MODE_HIDDEN) && s->mode & MODE_CURSOR) input_store_zero(b, CODE_CURSORON); } diff --git a/tmux.h b/tmux.h index b3371c98..6a7caefa 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.84 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: tmux.h,v 1.85 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -334,11 +334,12 @@ struct msg_resize_data { #define ATTR_ITALICS 0x40 /* Modes. */ -#define MODE_CURSOR 0x1 -#define MODE_INSERT 0x2 -#define MODE_KCURSOR 0x4 -#define MODE_KKEYPAD 0x8 -#define MODE_SAVED 0x10 +#define MODE_CURSOR 0x01 +#define MODE_INSERT 0x02 +#define MODE_KCURSOR 0x04 +#define MODE_KKEYPAD 0x08 +#define MODE_SAVED 0x10 +#define MODE_HIDDEN 0x20 /* * Virtual screen. This is stored as three blocks of 8-bit values, one for @@ -357,8 +358,8 @@ struct screen { u_int dx; /* display x size */ u_int dy; /* display y size */ - u_int ysize; /* actual y size */ - u_int ylimit; /* maximum y size */ + u_int hsize; /* history y size */ + u_int hlimit; /* history y limit */ u_int rupper; /* scroll region top */ u_int rlower; /* scroll region bottom */ @@ -378,7 +379,7 @@ struct screen { /* Screen display access macros. */ #define screen_x(s, x) (x) -#define screen_y(s, y) ((s)->ysize - (s)->dy + y) +#define screen_y(s, y) ((s)->hsize + y) #define screen_last_x(s) ((s)->dx - 1) #define screen_last_y(s) ((s)->dy - 1) @@ -388,9 +389,10 @@ struct screen { #define screen_in_x(s, x) ((x) < screen_size_x(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_hidden(s) ((s)->mode & MODE_HIDDEN) + /* Screen default contents. */ #define SCREEN_DEFDATA ' ' #define SCREEN_DEFATTR 0 @@ -421,6 +423,17 @@ struct input_ctx { ARRAY_DECL(, struct input_arg) args; }; +/* + * Window mode. Windows can be in several modes and this is used to call the + * right function to handle input and output. + */ +struct window_mode { + void (*init)(struct window *); + void (*resize)(struct window *, u_int, u_int); + void (*draw)(struct window *, struct buffer *, u_int, u_int); + void (*key)(struct window *, int); +}; + /* Window structure. */ struct window { char *name; @@ -435,6 +448,7 @@ struct window { #define WINDOW_BELL 0x1 struct screen screen; + const struct window_mode *mode; u_int references; }; @@ -607,6 +621,7 @@ extern const struct cmd_entry cmd_previous_window_entry; extern const struct cmd_entry cmd_refresh_client_entry; extern const struct cmd_entry cmd_rename_session_entry; extern const struct cmd_entry cmd_rename_window_entry; +extern const struct cmd_entry cmd_scroll_mode_entry; extern const struct cmd_entry cmd_select_window_entry; extern const struct cmd_entry cmd_send_prefix_entry; extern const struct cmd_entry cmd_set_option_entry; @@ -692,7 +707,7 @@ void input_store_one(struct buffer *, u_char, uint16_t); void input_store_two(struct buffer *, u_char, uint16_t, uint16_t); /* input-key.c */ -void input_translate_key(struct buffer *, int); +void input_key(struct buffer *, int); /* screen-display.c */ void screen_display_make_lines(struct screen *, u_int, u_int); @@ -731,7 +746,7 @@ u_char screen_stringcolour(const char *); void screen_create(struct screen *, u_int, u_int); void screen_destroy(struct screen *); void screen_resize(struct screen *, u_int, u_int); -void screen_draw(struct screen *, struct buffer *, u_int, u_int); +void screen_draw(struct screen *, struct buffer *, u_int, 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_move_lines(struct screen *, u_int, u_int, u_int); @@ -763,6 +778,12 @@ struct window *window_create( const char *, const char *, const char **, u_int, u_int); void window_destroy(struct window *); int window_resize(struct window *, u_int, u_int); +void window_parse(struct window *, struct buffer *); +void window_draw(struct window *, struct buffer *, u_int, u_int); +void window_key(struct window *, int); + +/* window-scroll.c */ +extern const struct window_mode window_scroll_mode; /* session.c */ extern struct sessions sessions; diff --git a/window-scroll.c b/window-scroll.c new file mode 100644 index 00000000..93d4f4e0 --- /dev/null +++ b/window-scroll.c @@ -0,0 +1,122 @@ +/* $Id: window-scroll.c,v 1.1 2007-11-21 13:11:41 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tmux.h" + +void window_scroll_init(struct window *); +void window_scroll_resize(struct window *, u_int, u_int); +void window_scroll_draw(struct window *, struct buffer *, u_int, u_int); +void window_scroll_key(struct window *, int); + +const struct window_mode window_scroll_mode = { + window_scroll_init, + window_scroll_resize, + window_scroll_draw, + window_scroll_key +}; + +u_int window_scroll_offset; +u_int window_scroll_size; + +void +window_scroll_init(struct window *w) +{ + window_scroll_offset = 0; + window_scroll_size = w->screen.hsize; +} + +void +window_scroll_resize(struct window *w, u_int sx, u_int sy) +{ +} + +void +window_scroll_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +{ + struct screen *s = &w->screen; + char buf[32]; + size_t len; + + if (s->hsize != window_scroll_size) { + window_scroll_offset += s->hsize - window_scroll_size; + window_scroll_size = s->hsize; + } + + screen_draw(s, b, py, ny, window_scroll_offset); + input_store_zero(b, CODE_CURSOROFF); + + if (py == 0 && ny > 0) { + len = screen_size_x(s); + if (len > (sizeof buf) - 1) + len = (sizeof buf) - 1; + len = xsnprintf(buf, len + 1, "{%u/%u}", + window_scroll_offset, s->hsize); + + input_store_two( + b, CODE_CURSORMOVE, 0, screen_size_x(s) - len + 1); + input_store_two(b, CODE_ATTRIBUTES, 0, status_colour); + buffer_write(b, buf, len); + } +} + +void +window_scroll_key(struct window *w, int key) +{ + u_int sy = screen_size_y(&w->screen); + + switch (key) { + case 'Q': + case 'q': + w->mode = NULL; + recalculate_sizes(); + server_redraw_window_all(w); + break; + case 'k': + case 'K': + case KEYC_UP: + if (window_scroll_offset < window_scroll_size) + window_scroll_offset++; + server_redraw_window_all(w); + break; + case 'j': + case 'J': + case KEYC_DOWN: + if (window_scroll_offset > 0) + window_scroll_offset--; + server_redraw_window_all(w); + break; + case '\025': + case KEYC_PPAGE: + if (window_scroll_offset + sy > window_scroll_size) + window_scroll_offset = window_scroll_size; + else + window_scroll_offset += sy; + server_redraw_window_all(w); + break; + case '\006': + case KEYC_NPAGE: + if (window_scroll_offset < sy) + window_scroll_offset = 0; + else + window_scroll_offset -= sy; + server_redraw_window_all(w); + break; + } +} diff --git a/window.c b/window.c index e79be717..1b991651 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.27 2007-11-20 21:42:29 nicm Exp $ */ +/* $Id: window.c,v 1.28 2007-11-21 13:11:41 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -195,6 +195,7 @@ window_create( w->fd = fd; w->in = buffer_create(BUFSIZ); w->out = buffer_create(BUFSIZ); + w->mode = NULL; screen_create(&w->screen, sx, sy); input_init(w); @@ -263,6 +264,8 @@ window_resize(struct window *w, u_int sx, u_int sy) ws.ws_col = sx; ws.ws_row = sy; + if (w->mode != NULL) + w->mode->resize(w, sx, sy); screen_resize(&w->screen, sx, sy); if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1) @@ -270,3 +273,28 @@ window_resize(struct window *w, u_int sx, u_int sy) return (0); } +void +window_parse(struct window *w, struct buffer *b) +{ + if (w->mode != NULL) + w->screen.mode |= MODE_HIDDEN; + input_parse(w, b); +} + +void +window_draw(struct window *w, struct buffer *b, u_int py, u_int ny) +{ + if (w->mode != NULL) + w->mode->draw(w, b, py, ny); + else + screen_draw(&w->screen, b, py, ny, 0); +} + +void +window_key(struct window *w, int key) +{ + if (w->mode != NULL) + w->mode->key(w, key); + else + input_key(w->out, key); +}