summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2007-11-20 21:42:29 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2007-11-20 21:42:29 +0000
commitceab127fac8b226ea2907261bdd6337b79d5d550 (patch)
tree558265c7e58356458b49a433d8fd3b43671251e6
parent0be6a3041ff58e716e6e44ff577dcc62685b3613 (diff)
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.
-rw-r--r--Makefile14
-rw-r--r--cmd-list-windows.c4
-rw-r--r--input.c130
-rw-r--r--key-bindings.c22
-rw-r--r--resize.c9
-rw-r--r--screen-display.c430
-rw-r--r--screen.c470
-rw-r--r--server-fn.c6
-rw-r--r--tmux.h83
-rw-r--r--window.c4
10 files changed, 617 insertions, 555 deletions
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 <nicm@users.sourceforge.net>
@@ -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 <nicm@users.sourceforge.net>
@@ -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 <nicm@users.sourceforge.net>
@@ -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 <nicm@users.sourceforge.net>
@@ -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 <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"
+
+/*
+ * 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 <nicm@users.sourceforge.net>
@@ -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");