From ceab127fac8b226ea2907261bdd6337b79d5d550 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 20 Nov 2007 21:42:29 +0000 Subject: [PATCH] Mass screen.c rename/tidy. Add a actual size (ysize) as distinct from display size (now dx,dy). Move functions which work on the displayed area into screen-display.c and tidy. Use macros consistently when accessing screen data (may want to move everything about again later!). This the first step on the road to scrollback. --- Makefile | 14 +- cmd-list-windows.c | 4 +- input.c | 130 ++++++------- key-bindings.c | 22 ++- resize.c | 9 +- screen-display.c | 430 +++++++++++++++++++++++++++++++++++++++++ screen.c | 470 ++++----------------------------------------- server-fn.c | 6 +- tmux.h | 83 +++++--- window.c | 4 +- 10 files changed, 617 insertions(+), 555 deletions(-) create mode 100644 screen-display.c diff --git a/Makefile b/Makefile index 41dc6ae3..8bbc2ed6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.43 2007-11-20 17:01:38 nicm Exp $ +# $Id: Makefile,v 1.44 2007-11-20 21:42:28 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -16,17 +16,17 @@ DEBUG= META?= \002 # C-b SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ - xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c window.c \ - session.c local.c log.c client.c client-msg.c client-fn.c key-string.c \ - key-bindings.c resize.c cmd.c cmd-new-session.c cmd-detach-client.c \ - cmd-list-sessions.c cmd-new-window.c cmd-next-window.c cmd-bind-key.c \ + xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \ + window.c session.c local.c log.c client.c client-msg.c client-fn.c \ + key-string.c key-bindings.c resize.c cmd.c cmd-new-session.c \ + cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \ cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \ cmd-set-option.c cmd-rename-window.c cmd-select-window.c \ cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \ cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \ - cmd-has-session.c cmd-link-window.c cmd-unlink-window.c \ + cmd-link-window.c cmd-unlink-window.c cmd-next-window.c \ cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ - cmd-switch-client.c + cmd-switch-client.c cmd-has-session.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 1340a7ae..c7bd1716 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-windows.c,v 1.8 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-list-windows.c,v 1.9 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -49,7 +49,7 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx) w = wl->window; ctx->print(ctx, "%d: %s \"%s\" (%s) [%ux%u]", wl->idx, w->name, w->screen.title, ttyname(w->fd), - w->screen.sx, w->screen.sy); + screen_size_x(&w->screen), screen_size_y(&w->screen)); } if (ctx->cmdclient != NULL) diff --git a/input.c b/input.c index f215b861..f9061aab 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.32 2007-11-20 18:46:32 nicm Exp $ */ +/* $Id: input.c,v 1.33 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -75,6 +75,13 @@ void input_handle_sequence_decstbm(struct input_ctx *); void input_handle_sequence_sgr(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 input_new_argument(struct input_ctx *ictx) { @@ -365,18 +372,16 @@ input_handle_character(u_char ch, struct input_ctx *ictx) log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch); - if (s->cx > s->sx || s->cy > s->sy - 1) - return; - - if (s->cx == s->sx) { + if (s->cx == screen_size_x(s)) { input_store8(ictx->b, '\r'); input_store8(ictx->b, '\n'); s->cx = 0; - screen_cursor_down_scroll(s); - } + screen_display_cursor_down(s); + } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) + return; - screen_write_character(s, ch); + screen_display_cursor_set(s, ch); input_store8(ictx->b, ch); s->cx++; @@ -393,7 +398,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) case '\0': /* NUL */ break; case '\n': /* LF */ - screen_cursor_down_scroll(s); + screen_display_cursor_down(s); break; case '\r': /* CR */ s->cx = 0; @@ -407,9 +412,9 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) break; case '\011': /* TAB */ s->cx = ((s->cx / 8) * 8) + 8; - if (s->cx > s->sx) { + if (s->cx > screen_last_x(s)) { s->cx = 0; - screen_cursor_down_scroll(s); + screen_display_cursor_down(s); } input_store_two( ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); @@ -430,7 +435,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) switch (ch) { case 'M': /* RI */ - screen_cursor_up_scroll(s); + screen_display_cursor_up(s); input_store_zero(ictx->b, CODE_REVERSEINDEX); break; default: @@ -521,7 +526,7 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx) log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u]", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args), - s->sx, s->sy, s->cx, s->cy); + screen_size_x(s), screen_size_y(s), s->cx, s->cy); for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) { iarg = &ARRAY_ITEM(&ictx->args, i); if (*iarg->data != '\0') @@ -576,10 +581,9 @@ input_handle_sequence_cud(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sy - s->cy - 1) { - log_debug3("cud: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_y(s) - s->cy); s->cy += n; input_store_one(ictx->b, CODE_CURSORDOWN, n); @@ -599,10 +603,9 @@ input_handle_sequence_cuf(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sx - s->cx - 1) { - log_debug3("cuf: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_x(s) - s->cx); s->cx += n; input_store_one(ictx->b, CODE_CURSORRIGHT, n); @@ -645,12 +648,11 @@ input_handle_sequence_dch(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sx - s->cx - 1) { - log_debug3("dch: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_x(s) - s->cx); - screen_delete_characters(s, s->cx, s->cy, n); + screen_display_delete_characters(s, s->cx, s->cy, n); input_store_one(ictx->b, CODE_DELETECHARACTER, n); } @@ -668,15 +670,14 @@ input_handle_sequence_dl(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sy - s->cy - 1) { - log_debug3("dl: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_y(s) - s->cy); if (s->cy < s->rupper || s->cy > s->rlower) - screen_delete_lines(s, s->cy, n); + screen_display_delete_lines(s, s->cy, n); else - screen_delete_lines_region(s, s->cy, n); + screen_display_delete_lines_region(s, s->cy, n); input_store_one(ictx->b, CODE_DELETELINE, n); } @@ -694,12 +695,11 @@ input_handle_sequence_ich(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sx - s->cx - 1) { - log_debug3("ich: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_x(s) - s->cx); - screen_insert_characters(s, s->cx, s->cy, n); + screen_display_insert_characters(s, s->cx, s->cy, n); input_store_one(ictx->b, CODE_INSERTCHARACTER, n); } @@ -717,14 +717,14 @@ input_handle_sequence_il(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sy - s->cy - 1) { - log_debug3("il: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_last_y(s) - s->cy); + if (s->cy < s->rupper || s->cy > s->rlower) - screen_insert_lines(s, s->cy, n); + screen_display_insert_lines(s, s->cy, n); else - screen_insert_lines_region(s, s->cy, n); + screen_display_insert_lines_region(s, s->cy, n); input_store_one(ictx->b, CODE_INSERTLINE, n); } @@ -742,10 +742,9 @@ input_handle_sequence_vpa(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sy) { - log_debug3("vpa: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_size_y(s)); s->cy = n - 1; input_store_two(ictx->b, CODE_CURSORMOVE, n, s->cx + 1); @@ -765,10 +764,9 @@ input_handle_sequence_hpa(struct input_ctx *ictx) if (input_get_argument(ictx, 0, &n, 1) != 0) return; - if (n == 0 || n > s->sx) { - log_debug3("hpa: out of range: %hu", n); + if (n == 0) return; - } + input_limit(n, 1, screen_size_x(s)); s->cx = n - 1; input_store_two(ictx->b, CODE_CURSORMOVE, s->cy + 1, n); @@ -790,14 +788,8 @@ input_handle_sequence_cup(struct input_ctx *ictx) if (input_get_argument(ictx, 1, &m, 1) != 0) return; - if (n == 0) - n = 1; - if (n > s->sy) - n = s->sy; - if (m == 0) - m = 1; - if (m > s->sx) - m = s->sx; + input_limit(n, 1, screen_size_y(s)); + input_limit(m, 1, screen_size_x(s)); s->cx = m - 1; s->cy = n - 1; @@ -824,10 +816,11 @@ input_handle_sequence_ed(struct input_ctx *ictx) switch (n) { case 0: - screen_fill_end_of_screen( - s, 0, s->cy, SCREEN_DEFDATA, s->attr, s->colr); + screen_display_fill_cursor_eos( + s, SCREEN_DEFDATA, s->attr, s->colr); + input_store_zero(ictx->b, CODE_CLEARLINE); - for (i = s->cy + 1; i < s->sy; i++) { + for (i = s->cy + 1; i < screen_size_y(s); i++) { input_store_two(ictx->b, CODE_CURSORMOVE, i + 1, 1); input_store_zero(ictx->b, CODE_CLEARLINE); } @@ -835,8 +828,10 @@ input_handle_sequence_ed(struct input_ctx *ictx) ictx->b, CODE_CURSORMOVE, s->cy + 1, s->cx + 1); break; case 2: - screen_fill_screen(s, SCREEN_DEFDATA, s->attr, s->colr); - for (i = 0; i < s->sy; i++) { + screen_display_fill_lines( + s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr); + + 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); } @@ -865,17 +860,18 @@ input_handle_sequence_el(struct input_ctx *ictx) switch (n) { case 0: - screen_fill_end_of_line( - s, s->cx, s->cy, SCREEN_DEFDATA, s->attr, s->colr); + screen_display_fill_cursor_eol( + s, SCREEN_DEFDATA, s->attr, s->colr); input_store_zero(ictx->b, CODE_CLEARENDOFLINE); break; case 1: - screen_fill_start_of_line( - s, s->cx, s->cy, SCREEN_DEFDATA, s->attr, s->colr); + screen_display_fill_cursor_bol( + s, SCREEN_DEFDATA, s->attr, s->colr); input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE); break; case 2: - screen_fill_line(s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); + screen_display_fill_line( + s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); input_store_zero(ictx->b, CODE_CLEARLINE); break; } @@ -1008,17 +1004,11 @@ input_handle_sequence_decstbm(struct input_ctx *ictx) /* XXX this will catch [0;0r and [;r etc too, is this right? */ if (n == 0 && m == 0) { n = 1; - m = s->sy; + m = screen_size_y(s); } - if (n == 0) - n = 1; - if (n > s->sy) - n = s->sy; - if (m == 0) - m = 1; - if (m > s->sy) - m = s->sy; + input_limit(n, 1, screen_size_y(s)); + input_limit(m, 1, screen_size_y(s)); if (n > m) { log_debug3("decstbm: out of range: %hu,%hu", n, m); diff --git a/key-bindings.c b/key-bindings.c index 7be5df60..0af94f8d 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.16 2007-11-20 18:11:37 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.17 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -166,15 +166,18 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) va_list ap; char *msg; size_t size; - u_int i; + u_int i, sx, sy; + + sx = screen_size_x(s); + sy = screen_size_y(s); buffer_ensure(c->out, sizeof hdr); buffer_add(c->out, sizeof hdr); size = BUFFER_USED(c->out); - if (line == 2 * s->sy || !(c->flags & CLIENT_HOLD)) { + if (line == 2 * sy || !(c->flags & CLIENT_HOLD)) { input_store_zero(c->out, CODE_CURSOROFF); - for (i = 0; i < s->sy; i++) { + for (i = 0; i < sy; i++) { input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1); input_store_zero(c->out, CODE_CLEARLINE); } @@ -184,20 +187,19 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) line = 0; c->flags |= CLIENT_HOLD; } - if (line >= s->sy) { - input_store_two( - c->out, CODE_CURSORMOVE, line - s->sy + 1, s->sx / 2); + if (line >= sy) { + input_store_two(c->out, CODE_CURSORMOVE, line - sy + 1, sx / 2); } line++; va_start(ap, fmt); xvasprintf(&msg, fmt, ap); va_end(ap); - if (strlen(msg) > s->sx / 2) - msg[s->sx / 2] = '\0'; + if (strlen(msg) > sx / 2) + msg[sx / 2] = '\0'; buffer_write(c->out, msg, strlen(msg)); - if (line != s->sy && line != 2 * s->sy) { + if (line != sy && line != 2 * sy) { input_store8(c->out, '\r'); input_store8(c->out, '\n'); } diff --git a/resize.c b/resize.c index 71392604..2e9380c3 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.4 2007-10-19 10:21:35 nicm Exp $ */ +/* $Id: resize.c,v 1.5 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -107,11 +107,12 @@ recalculate_sizes(void) if (ssx == UINT_MAX || ssy == UINT_MAX) continue; - if (w->screen.sx == ssx && w->screen.sy == ssy) + if (screen_size_x(&w->screen) == ssx && + screen_size_y(&w->screen) == ssy) continue; - log_debug("window size %u,%u (was %u,%u)", - ssx, ssy, w->screen.sx, w->screen.sy); + log_debug("window size %u,%u (was %u,%u)", ssx, ssy, + screen_size_x(&w->screen), screen_size_y(&w->screen)); server_clear_window_cur(w); window_resize(w, ssx, ssy); diff --git a/screen-display.c b/screen-display.c new file mode 100644 index 00000000..5f2790aa --- /dev/null +++ b/screen-display.c @@ -0,0 +1,430 @@ +/* $Id: screen-display.c,v 1.1 2007-11-20 21:42:29 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +/* + * Screen display modification functions. These alter the displayed portion + * of the screen. + */ + +/* Create a region of lines. */ +void +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)) + fatalx("bad value"); + screen_make_lines(s, screen_y(s, py), ny); +} + +/* Free a region of lines. */ +void +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)) + fatalx("bad value"); + screen_free_lines(s, screen_y(s, py), ny); +} + +/* Move a set of lines. */ +void +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)) + fatalx("bad value"); + if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) + fatalx("bad value"); + screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny); +} + +/* Fill a set of lines. */ +void +screen_display_fill_lines( + struct screen *s, u_int py, 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)) + fatalx("bad value"); + screen_fill_lines(s, screen_y(s, py), ny, data, attr, colr); +} + +/* Fill a set of cellss. */ +void +screen_display_fill_cells(struct screen *s, + 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); + + s->grid_data[py][px] = ch; + s->grid_attr[py][px] = s->attr; + s->grid_colr[py][px] = 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. */ +void +screen_display_scroll_region_up(struct screen *s) +{ + /* + * Scroll scrolling region up: + * - delete rupper + * - move rupper + 1 to rlower to rupper + * - make new line at rlower + * + * Example: region is 12 to 24. + * rlower = 24, rupper = 12 + * screen_free_lines(s, 12, 1); + * screen_move_lines(s, 12, 13, 12); + * screen_make_lines(s, 24, 1); + */ + + screen_display_free_lines(s, s->rupper, 1); + + if (s->rupper != s->rlower) { + screen_display_move_lines(s, + s->rupper, s->rupper + 1, s->rlower - s->rupper); + } + + 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. */ +void +screen_display_scroll_region_down(struct screen *s) +{ + /* + * Scroll scrolling region down: + * - delete rlower + * - move rupper to rlower - 1 to rupper + 1 + * - make new line at rupper + * + * Example: region is 12 to 24. + * rlower = 24, rupper = 12 + * screen_free_lines(s, 24, 1); + * screen_move_lines(s, 13, 12, 12); + * screen_make_lines(s, 12, 1); + */ + + screen_display_free_lines(s, s->rlower, 1); + + if (s->rupper != s->rlower) { + screen_display_move_lines(s, + s->rupper + 1, s->rupper, s->rlower - s->rupper); + } + + screen_display_make_lines(s, s->rupper, 1); + screen_display_fill_lines( + s, s->rupper, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); +} + +/* Insert lines. */ +void +screen_display_insert_lines(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_y(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > screen_last_y(s)) + ny = screen_last_y(s) - py; + + /* + * Insert range of ny lines at py: + * - Free ny lines from end of screen. + * - Move from py to end of screen - ny to py + ny. + * - Create ny lines at py. + * + * Example: insert 2 lines at 4. + * sy = 10, py = 4, ny = 2 + * screen_free_lines(s, 8, 2); - delete lines 8,9 + * screen_move_lines(s, 6, 4, 4); - move 4,5,6,7 to 6,7,8,9 + * screen_make_lines(s, 4, 2); - make lines 4,5 + */ + + screen_display_free_lines(s, screen_size_y(s) - ny, ny); + + if (py != screen_last_y(s)) { + screen_display_move_lines( + s, py + ny, py, screen_size_y(s) - py - ny); + } + + screen_display_make_lines(s, py, ny); +} + +/* Insert lines in region. */ +void +screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_region(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > s->rlower) + ny = s->rlower - py; + + /* + * Insert range of ny lines at py: + * - Free ny lines from end of screen. + * - Move from py to end of screen - ny to py + ny. + * - Create ny lines at py. + * + * Example: insert 2 lines at 4. + * ryu = 11, ryl = 16, py = 13, ny = 2 + * screen_free_lines(s, 15, 2); - delete lines 15,16 + * screen_move_lines(s, 13, 15, 2);- move 13,14 to 15,16 + * screen_make_lines(s, 13, 2); - make lines 13,14 + */ + + screen_display_free_lines(s, (s->rlower + 1) - ny, ny); + + if (py != s->rlower) { + screen_display_move_lines( + s, py + ny, py, (s->rlower + 1) - py - ny); + } + + screen_display_make_lines(s, py, ny); +} + +/* Delete lines. */ +void +screen_display_delete_lines(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_y(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > screen_last_y(s)) + ny = screen_last_y(s) - py; + + /* + * Delete range of ny lines at py: + * - Free ny lines at py. + * - Move from py + ny to end of screen to py. + * - Free and recreate last ny lines. + * + * Example: delete lines 3,4. + * sy = 10, py = 3, ny = 2 + * screen_free_lines(s, 3, 2); - delete lines 3,4 + * screen_move_lines(s, 3, 5, 5); - move 5,6,7,8,9 to 3 + * screen_make_lines(s, 8, 2); - make lines 8,9 + */ + + screen_display_free_lines(s, py, ny); + + if (py != screen_last_y(s)) { + screen_display_move_lines( + s, py, py + ny, screen_size_y(s) - py - ny); + } + + screen_display_make_lines(s, screen_size_y(s) - ny, ny); +} + +/* Delete lines inside scroll region. */ +void +screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_region(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > s->rlower) + ny = s->rlower - py; + + /* + * Delete range of ny lines at py: + * - Free ny lines at py. + * - Move from py + ny to end of region to py. + * - Free and recreate last ny lines. + * + * Example: delete lines 13,14. + * ryu = 11, ryl = 16, py = 13, ny = 2 + * screen_free_lines(s, 13, 2); - delete lines 13,14 + * screen_move_lines(s, 15, 16, 2);- move 15,16 to 13 + * screen_make_lines(s, 15, 16); - make lines 15,16 + */ + + screen_display_free_lines(s, py, ny); + + if (py != s->rlower) { + screen_display_move_lines( + s, py, py + ny, (s->rlower + 1) - py - ny); + } + + screen_display_make_lines(s, (s->rlower + 1) - ny, ny); +} + +/* Insert characters. */ +void +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; + + /* + * Inserting a range of nx at px. + * + * - Move sx - (px + nx) from px to px + nx. + * - Clear the range at px. + */ + + if (px + nx != screen_last_x(s)) { + mx = screen_last_x(s) - (px + nx); + memmove(&s->grid_data[py][px + nx], &s->grid_data[py][px], mx); + memmove(&s->grid_attr[py][px + nx], &s->grid_attr[py][px], mx); + memmove(&s->grid_colr[py][px + nx], &s->grid_colr[py][px], mx); + } + memset(&s->grid_data[py][px], SCREEN_DEFDATA, nx); + memset(&s->grid_attr[py][px], SCREEN_DEFATTR, nx); + memset(&s->grid_colr[py][px], SCREEN_DEFCOLR, nx); +} + +/* Delete characters. */ +void +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; + + /* + * Deleting the range from px to px + nx. + * + * - Move sx - (px + nx) from px + nx to px. + * - Clear the range from the last x - (rx - lx) to the last x. + */ + + if (px + nx != screen_last_x(s)) { + mx = screen_last_x(s) - (px + nx); + memmove(&s->grid_data[py][px], &s->grid_data[py][px + nx], mx); + memmove(&s->grid_attr[py][px], &s->grid_attr[py][px + nx], mx); + memmove(&s->grid_colr[py][px], &s->grid_colr[py][px + nx], mx); + } + + memset(&s->grid_data[py][screen_size_x(s) - nx], SCREEN_DEFDATA, 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); +} diff --git a/screen.c b/screen.c index d4bee630..a59cadae 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.24 2007-11-20 18:46:32 nicm Exp $ */ +/* $Id: screen.c,v 1.25 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,21 +28,6 @@ * XXX Much of this file sucks. */ -void screen_free_lines(struct screen *, u_int, u_int); -void screen_make_lines(struct screen *, u_int, u_int); -void screen_move_lines(struct screen *, u_int, u_int, u_int); -void screen_fill_lines( - struct screen *, u_int, u_int, u_char, u_char, u_char); - -#define screen_last_y(s) ((s)->sy - 1) -#define screen_last_x(s) ((s)->sx - 1) - -#define screen_range_y(lx, rx) (((rx) - (lx)) + 1) -#define screen_range_x(ux, lx) (((lx) - (ux)) + 1) - -#define screen_offset_y(py, ny) ((py) + (ny) - 1) -#define screen_offset_x(px, nx) ((px) + (nx) - 1) - /* Colour to string. */ const char * screen_colourstring(u_char c) @@ -97,15 +82,18 @@ screen_stringcolour(const char *s) /* Create a new screen. */ void -screen_create(struct screen *s, u_int sx, u_int sy) +screen_create(struct screen *s, u_int dx, u_int dy) { - s->sx = sx; - s->sy = sy; + s->dx = dx; + s->dy = dy; s->cx = 0; s->cy = 0; s->rupper = 0; - s->rlower = screen_last_y(s); + s->rlower = s->dy - 1; + + s->ysize = dy; + s->ylimit = SHRT_MAX; s->attr = SCREEN_DEFATTR; s->colr = SCREEN_DEFCOLR; @@ -113,11 +101,10 @@ screen_create(struct screen *s, u_int sx, u_int sy) s->mode = MODE_CURSOR; *s->title = '\0'; - s->grid_data = xmalloc(sy * (sizeof *s->grid_data)); - s->grid_attr = xmalloc(sy * (sizeof *s->grid_attr)); - s->grid_colr = xmalloc(sy * (sizeof *s->grid_colr)); - screen_make_lines(s, 0, sy); - screen_fill_screen(s, SCREEN_DEFDATA, 0, SCREEN_DEFCOLR); + s->grid_data = xmalloc(dy * (sizeof *s->grid_data)); + s->grid_attr = xmalloc(dy * (sizeof *s->grid_attr)); + s->grid_colr = xmalloc(dy * (sizeof *s->grid_colr)); + screen_make_lines(s, 0, dy); } /* Resize screen. */ @@ -126,7 +113,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy) { u_int i, ox, oy, ny; - if (sx == s->sx && sy == s->sy) + if (sx == s->dx && sy == s->dy) return; if (sx < 1) @@ -134,16 +121,16 @@ screen_resize(struct screen *s, u_int sx, u_int sy) if (sy < 1) sy = 1; - ox = s->sx; - oy = s->sy; + ox = s->dx; + oy = s->dy; log_debug("resizing screen (%u, %u) -> (%u, %u)", ox, oy, sx, sy); - s->sx = sx; - s->sy = sy; + s->dx = sx; + s->dy = sy; s->rupper = 0; - s->rlower = screen_last_y(s); + s->rlower = s->dy - 1; if (sy < oy) { ny = oy - sy; @@ -190,7 +177,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy) s->grid_data[i] = xmalloc(sx); s->grid_attr[i] = xmalloc(sx); s->grid_colr[i] = xmalloc(sx); - screen_fill_line(s, i, + screen_display_fill_line(s, i, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } sy = oy; @@ -203,7 +190,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy) 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_fill_end_of_line(s, ox, i, + screen_display_fill_cells(s, ox, i, s->dx - ox, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } @@ -217,7 +204,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy) void screen_destroy(struct screen *s) { - screen_free_lines(s, 0, s->sy); + screen_free_lines(s, 0, s->dy); xfree(s->grid_data); xfree(s->grid_attr); xfree(s->grid_colr); @@ -230,7 +217,7 @@ screen_draw(struct screen *s, struct buffer *b, u_int uy, u_int ly) u_char attr, colr; u_int i, j; - if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) + if (uy > s->dy - 1 || ly > s->dy - 1 || ly < uy) fatalx("bad range"); /* XXX. This is naive and rough right now. */ @@ -263,35 +250,28 @@ screen_draw(struct screen *s, struct buffer *b, u_int uy, u_int ly) input_store_zero(b, CODE_CURSORON); } -/* Make a range of lines. */ +/* Create a range of lines. */ void screen_make_lines(struct screen *s, u_int py, u_int ny) { u_int i; - log_debug("making lines %u,%u", py, ny); - - if (py > screen_last_y(s) || py + ny - 1 > screen_last_y(s)) - fatalx("bad range"); - for (i = py; i < py + ny; i++) { - s->grid_data[i] = xmalloc(s->sx); - s->grid_attr[i] = xmalloc(s->sx); - s->grid_colr[i] = xmalloc(s->sx); + s->grid_data[i] = xmalloc(s->dx); + s->grid_attr[i] = xmalloc(s->dx); + s->grid_colr[i] = xmalloc(s->dx); } + screen_fill_lines( + s, py, ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); } -/* Free a range of lines. */ + +/* Free a range of ny lines at py. */ void screen_free_lines(struct screen *s, u_int py, u_int ny) { u_int i; - log_debug("freeing lines %u,%u", py, ny); - - if (py > screen_last_y(s) || py + ny - 1 > screen_last_y(s)) - fatalx("bad range"); - for (i = py; i < py + ny; i++) { xfree(s->grid_data[i]); xfree(s->grid_attr[i]); @@ -303,15 +283,6 @@ screen_free_lines(struct screen *s, u_int py, u_int ny) void screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) { - log_debug("moving lines %u,%u to %u", py, ny, dy); - - if (py > screen_last_y(s) || py + ny - 1 > screen_last_y(s)) - fatalx("bad range"); - if (dy > screen_last_y(s) || dy == py) - fatalx("bad destination"); - if (dy + ny - 1 > screen_last_y(s)) - fatalx("bad size"); - memmove( &s->grid_data[dy], &s->grid_data[py], ny * (sizeof *s->grid_data)); memmove( @@ -327,383 +298,16 @@ screen_fill_lines( { u_int i; - log_debug("filling lines %u,%u", py, ny); - - if (py > screen_last_y(s) || py + ny - 1 > screen_last_y(s)) - fatalx("bad range"); - for (i = py; i < py + ny; i++) - screen_fill_line(s, i, data, attr, colr); + screen_fill_cells(s, 0, i, s->dx, data, attr, colr); } -/* Write a single character to the screen at the cursor. */ +/* Fill a range of cells. */ void -screen_write_character(struct screen *s, u_char ch) +screen_fill_cells(struct screen *s, + u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr) { - s->grid_data[s->cy][s->cx] = ch; - s->grid_attr[s->cy][s->cx] = s->attr; - s->grid_colr[s->cy][s->cx] = s->colr; -} - -/* Move cursor up and scroll if necessary. */ -void -screen_cursor_up_scroll(struct screen *s) -{ - if (s->cy == s->rupper) - screen_scroll_region_down(s); - else if (s->cy > 0) - s->cy--; -} - -/* Move cursor down and scroll if necessary. */ -void -screen_cursor_down_scroll(struct screen *s) -{ - if (s->cy == s->rlower) - screen_scroll_region_up(s); - else if (s->cy < screen_last_y(s)) - s->cy++; -} - -/* Scroll region up. */ -void -screen_scroll_region_up(struct screen *s) -{ - log_debug("scrolling region up: %u:%u", s->rupper, s->rlower); - - /* - * Scroll scrolling region up: - * - delete rupper - * - move rupper + 1 to rlower to rupper - * - make new line at rlower - * - * Example: region is 12 to 24. - * rlower = 24, rupper = 12 - * screen_free_lines(s, 12, 1); - * screen_move_lines(s, 12, 13, 12); - * screen_make_lines(s, 24, 1); - */ - - screen_free_lines(s, s->rupper, 1); - - if (s->rupper != s->rlower) { - screen_move_lines(s, - s->rupper, s->rupper + 1, s->rlower - s->rupper); - } - - screen_make_lines(s, s->rlower, 1); - screen_fill_lines( - s, s->rlower, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Scroll region down. */ -void -screen_scroll_region_down(struct screen *s) -{ - log_debug("scrolling region down: %u:%u", s->rupper, s->rlower); - - /* - * Scroll scrolling region down: - * - delete rlower - * - move rupper to rlower - 1 to rupper + 1 - * - make new line at rupper - * - * Example: region is 12 to 24. - * rlower = 24, rupper = 12 - * screen_free_lines(s, 24, 1); - * screen_move_lines(s, 13, 12, 12); - * screen_make_lines(s, 12, 1); - */ - - screen_free_lines(s, s->rlower, 1); - - if (s->rupper != s->rlower) { - screen_move_lines(s, - s->rupper + 1, s->rupper, s->rlower - s->rupper); - } - - screen_make_lines(s, s->rupper, 1); - screen_fill_lines( - s, s->rupper, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Scroll screen up. */ -void -screen_scroll_up(struct screen *s, u_int ny) -{ - screen_delete_lines(s, 0, ny); -} - -/* Scroll screen down. */ -void -screen_scroll_down(struct screen *s, u_int ny) -{ - screen_insert_lines(s, 0, ny); -} - -/* Fill entire screen. */ -void -screen_fill_screen(struct screen *s, u_char data, u_char attr, u_char colr) -{ - screen_fill_end_of_screen(s, 0, 0, data, attr, colr); -} - -/* Fill single line. */ -void -screen_fill_line( - struct screen *s, u_int py, u_char data, u_char attr, u_char colr) -{ - screen_fill_end_of_line(s, 0, py, data, attr, colr); -} - -/* Fill to end of screen. */ -void -screen_fill_end_of_screen( - struct screen *s, u_int px, u_int py, u_char data, u_char attr, u_char colr) -{ - if (py > screen_last_y(s)) - return; - - if (px != 0) { - screen_fill_end_of_line(s, px, py, data, attr, colr); - if (py++ > screen_last_y(s)) - return; - } - - while (py <= screen_last_y(s)) { - screen_fill_line(s, py, data, attr, colr); - py++; - } -} - -/* Fill to end of line. */ -void -screen_fill_end_of_line( - struct screen *s, u_int px, u_int py, u_char data, u_char attr, u_char colr) -{ - if (px > screen_last_x(s)) - return; - if (py > screen_last_y(s)) - return; - - memset(&s->grid_data[py][px], data, s->sx - px); - memset(&s->grid_attr[py][px], attr, s->sx - px); - memset(&s->grid_colr[py][px], colr, s->sx - px); -} - -/* Fill to start of line. */ -void -screen_fill_start_of_line( - struct screen *s, u_int px, u_int py, u_char data, u_char attr, u_char colr) -{ - if (px > screen_last_x(s)) - return; - if (py > screen_last_y(s)) - return; - - memset(s->grid_data[py], data, px); - memset(s->grid_attr[py], attr, px); - memset(s->grid_colr[py], colr, px); -} - -/* Insert lines. */ -void -screen_insert_lines(struct screen *s, u_int py, u_int ny) -{ - if (py > screen_last_y(s)) - return; - - if (py + ny > screen_last_y(s)) - ny = screen_last_y(s) - py; - log_debug("inserting lines: %u,%u", py, ny); - - /* - * Insert range of ny lines at py: - * - Free ny lines from end of screen. - * - Move from py to end of screen - ny to py + ny. - * - Create ny lines at py. - * - * Example: insert 2 lines at 4. - * sy = 10, py = 4, ny = 2 - * screen_free_lines(s, 8, 2); - delete lines 8,9 - * screen_move_lines(s, 6, 4, 4); - move 4,5,6,7 to 6,7,8,9 - * screen_make_lines(s, 4, 2); - make lines 4,5 - */ - - screen_free_lines(s, s->sy - ny, ny); - - if (py != screen_last_y(s)) - screen_move_lines(s, py + ny, py, s->sy - py - ny); - - screen_make_lines(s, py, ny); - screen_fill_lines( - s, py, ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Insert lines in region. */ -void -screen_insert_lines_region(struct screen *s, u_int py, u_int ny) -{ - if (py < s->rupper || py > s->rlower) - return; - if (py + ny > s->rlower) - ny = s->rlower - py; - log_debug("inserting lines in region: %u,%u (%u,%u)", py, ny, - s->rupper, s->rlower); - - /* - * Insert range of ny lines at py: - * - Free ny lines from end of screen. - * - Move from py to end of screen - ny to py + ny. - * - Create ny lines at py. - * - * Example: insert 2 lines at 4. - * ryu = 11, ryl = 16, py = 13, ny = 2 - * screen_free_lines(s, 15, 2); - delete lines 15,16 - * screen_move_lines(s, 13, 15, 2);- move 13,14 to 15,16 - * screen_make_lines(s, 13, 2); - make lines 13,14 - */ - - screen_free_lines(s, (s->rlower + 1) - ny, ny); - - if (py != s->rlower) - screen_move_lines(s, py + ny, py, (s->rlower + 1) - py - ny); - - screen_make_lines(s, py, ny); - screen_fill_lines( - s, py, ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Delete lines. */ -void -screen_delete_lines(struct screen *s, u_int py, u_int ny) -{ - if (py > screen_last_y(s)) - return; - - if (py + ny > screen_last_y(s)) - ny = screen_last_y(s) - py; - log_debug("deleting lines: %u,%u", py, ny); - - /* - * Delete range of ny lines at py: - * - Free ny lines at py. - * - Move from py + ny to end of screen to py. - * - Free and recreate last ny lines. - * - * Example: delete lines 3,4. - * sy = 10, py = 3, ny = 2 - * screen_free_lines(s, 3, 2); - delete lines 3,4 - * screen_move_lines(s, 3, 5, 5); - move 5,6,7,8,9 to 3 - * screen_make_lines(s, 8, 2); - make lines 8,9 - */ - - screen_free_lines(s, py, ny); - - if (py != screen_last_y(s)) - screen_move_lines(s, py, py + ny, s->sy - py - ny); - - screen_make_lines(s, s->sy - ny, ny); - screen_fill_lines( - s, s->sy - ny, ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Delete lines inside scroll region. */ -void -screen_delete_lines_region(struct screen *s, u_int py, u_int ny) -{ - if (py < s->rupper || py > s->rlower) - return; - if (py + ny > s->rlower) - ny = s->rlower - py; - log_debug("deleting lines in region: %u,%u (%u,%u)", py, ny, - s->rupper, s->rlower); - - /* - * Delete range of ny lines at py: - * - Free ny lines at py. - * - Move from py + ny to end of region to py. - * - Free and recreate last ny lines. - * - * Example: delete lines 13,14. - * ryu = 11, ryl = 16, py = 13, ny = 2 - * screen_free_lines(s, 13, 2); - delete lines 13,14 - * screen_move_lines(s, 15, 16, 2);- move 15,16 to 13 - * screen_make_lines(s, 15, 16); - make lines 15,16 - */ - - screen_free_lines(s, py, ny); - - if (py != s->rlower) - screen_move_lines(s, py, py + ny, (s->rlower + 1) - py - ny); - - screen_make_lines(s, (s->rlower + 1) - ny, ny); - screen_fill_lines(s, (s->rlower + 1) - ny, - ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); -} - -/* Insert characters. */ -void -screen_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) -{ - u_int lx, rx; - - if (px > screen_last_x(s) || py > screen_last_y(s)) - return; - - lx = px; - rx = screen_offset_x(px, nx); - if (rx > screen_last_x(s)) - rx = screen_last_x(s); - - /* - * Inserting a range from lx to rx, inclusive. - * - * - If rx is not the last x, move from lx to rx + 1. - * - Clear the range from lx to rx. - */ - if (rx != screen_last_x(s)) { - nx = screen_range_x(rx + 1, screen_last_x(s)); - memmove(&s->grid_data[py][rx + 1], &s->grid_data[py][lx], nx); - memmove(&s->grid_attr[py][rx + 1], &s->grid_attr[py][lx], nx); - memmove(&s->grid_colr[py][rx + 1], &s->grid_colr[py][lx], nx); - } - memset(&s->grid_data[py][lx], SCREEN_DEFDATA, screen_range_x(lx, rx)); - memset(&s->grid_attr[py][lx], SCREEN_DEFATTR, screen_range_x(lx, rx)); - memset(&s->grid_colr[py][lx], SCREEN_DEFCOLR, screen_range_x(lx, rx)); -} - -/* Delete characters. */ -void -screen_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) -{ - u_int lx, rx; - - if (px > screen_last_x(s) || py > screen_last_y(s)) - return; - - lx = px; - rx = screen_offset_x(px, nx); - if (rx > screen_last_x(s)) - rx = screen_last_x(s); - - /* - * Deleting the range from lx to rx, inclusive. - * - * - If rx is not the last x, move the range from rx + 1 to lx. - * - Clear the range from the last x - (rx - lx) to the last x. - */ - - if (rx != screen_last_x(s)) { - nx = screen_range_x(rx + 1, screen_last_x(s)); - memmove(&s->grid_data[py][lx], &s->grid_data[py][rx + 1], nx); - memmove(&s->grid_attr[py][lx], &s->grid_attr[py][rx + 1], nx); - memmove(&s->grid_colr[py][lx], &s->grid_colr[py][rx + 1], nx); - } - - /* If lx == rx, then nx = 1. */ - nx = screen_range_x(lx, rx); - memset(&s->grid_data[py][s->sx - nx], SCREEN_DEFDATA, nx); - memset(&s->grid_attr[py][s->sx - nx], SCREEN_DEFATTR, nx); - memset(&s->grid_colr[py][s->sx - nx], SCREEN_DEFCOLR, nx); + memset(&s->grid_data[py][px], data, nx); + memset(&s->grid_attr[py][px], attr, nx); + memset(&s->grid_colr[py][px], colr, nx); } diff --git a/server-fn.c b/server-fn.c index 68ebc374..40a35400 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.25 2007-11-20 18:11:37 nicm Exp $ */ +/* $Id: server-fn.c,v 1.26 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -175,7 +175,7 @@ server_clear_client(struct client *c) size = BUFFER_USED(c->out); input_store_zero(c->out, CODE_CURSOROFF); - for (i = 0; i < s->sy; i++) { + for (i = 0; i < screen_size_y(s); i++) { input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1); input_store_zero(c->out, CODE_CLEARLINE); } @@ -200,7 +200,7 @@ server_redraw_client(struct client *c) buffer_add(c->out, sizeof hdr); size = BUFFER_USED(c->out); - screen_draw(s, c->out, 0, s->sy - 1); + screen_draw(s, c->out, 0, screen_last_y(s)); size = BUFFER_USED(c->out) - size; log_debug("redrawing screen, %zu bytes", size); diff --git a/tmux.h b/tmux.h index d270a2e5..b3371c98 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.83 2007-11-20 18:46:32 nicm Exp $ */ +/* $Id: tmux.h,v 1.84 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -354,8 +354,11 @@ struct screen { u_char **grid_attr; u_char **grid_colr; - u_int sx; /* size x */ - u_int sy; /* size y */ + 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 rupper; /* scroll region top */ u_int rlower; /* scroll region bottom */ @@ -373,6 +376,21 @@ struct screen { int mode; }; +/* Screen display access macros. */ +#define screen_x(s, x) (x) +#define screen_y(s, y) ((s)->ysize - (s)->dy + y) + +#define screen_last_x(s) ((s)->dx - 1) +#define screen_last_y(s) ((s)->dy - 1) + +#define screen_size_x(s) ((s)->dx) +#define screen_size_y(s) ((s)->dy) + +#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) + /* Screen default contents. */ #define SCREEN_DEFDATA ' ' #define SCREEN_DEFATTR 0 @@ -676,6 +694,37 @@ void input_store_two(struct buffer *, u_char, uint16_t, uint16_t); /* input-key.c */ void input_translate_key(struct buffer *, int); +/* screen-display.c */ +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_move_lines(struct screen *, u_int, u_int, u_int); +void screen_display_fill_lines( + struct screen *, 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_down(struct screen *); +void screen_display_insert_lines(struct screen *, u_int, u_int); +void screen_display_insert_lines_region(struct screen *, u_int, u_int); +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_insert_characters(struct screen *, u_int, u_int, u_int); +void screen_display_delete_characters(struct screen *, u_int, u_int, u_int); + /* screen.c */ const char *screen_colourstring(u_char); u_char screen_stringcolour(const char *); @@ -683,27 +732,13 @@ 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_write_character(struct screen *, u_char); -void screen_insert_lines(struct screen *, u_int, u_int); -void screen_insert_lines_region(struct screen *, u_int, u_int); -void screen_delete_lines(struct screen *, u_int, u_int); -void screen_delete_lines_region(struct screen *, u_int, u_int); -void screen_insert_characters(struct screen *, u_int, u_int, u_int); -void screen_delete_characters(struct screen *, u_int, u_int, u_int); -void screen_cursor_up_scroll(struct screen *); -void screen_cursor_down_scroll(struct screen *); -void screen_scroll_region_up(struct screen *); -void screen_scroll_region_down(struct screen *); -void screen_scroll_up(struct screen *, u_int); -void screen_scroll_down(struct screen *, u_int); -void screen_fill_screen(struct screen *, u_char, u_char, u_char); -void screen_fill_line(struct screen *, u_int, u_char, u_char, u_char); -void screen_fill_end_of_screen( - struct screen *, u_int, u_int, u_char, u_char, u_char); -void screen_fill_end_of_line( - struct screen *, u_int, u_int, u_char, u_char, u_char); -void screen_fill_start_of_line( - struct screen *, u_int, u_int, u_char, u_char, u_char); +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); +void screen_fill_lines( + struct screen *, u_int, u_int, u_char, u_char, u_char); +void screen_fill_cells( + struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); /* local.c */ int local_init(struct buffer **, struct buffer **); diff --git a/window.c b/window.c index 0c029b4c..e79be717 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.26 2007-11-07 19:41:17 nicm Exp $ */ +/* $Id: window.c,v 1.27 2007-11-20 21:42:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -256,7 +256,7 @@ window_resize(struct window *w, u_int sx, u_int sy) { struct winsize ws; - if (sx == w->screen.sx && sy == w->screen.sy) + if (sx == screen_size_x(&w->screen) && sy == screen_size_y(&w->screen)) return (-1); memset(&ws, 0, sizeof ws);