aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES12
-rw-r--r--GNUmakefile8
-rw-r--r--Makefile5
-rw-r--r--TODO125
-rw-r--r--cmd-list-windows.c23
-rw-r--r--grid-view.c199
-rw-r--r--grid.c353
-rw-r--r--input.c362
-rw-r--r--log.c5
-rw-r--r--screen-display.c477
-rw-r--r--screen-redraw.c118
-rw-r--r--screen-write.c737
-rw-r--r--screen.c365
-rw-r--r--server-msg.c6
-rw-r--r--server.c28
-rw-r--r--status.c127
-rw-r--r--tmux.111
-rw-r--r--tmux.c12
-rw-r--r--tmux.h379
-rw-r--r--tty.c780
-rw-r--r--utf8.c133
-rw-r--r--window-copy.c264
-rw-r--r--window-more.c39
-rw-r--r--window-scroll.c63
24 files changed, 2342 insertions, 2289 deletions
diff --git a/CHANGES b/CHANGES
index c55af603..c6f2dff6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+25 September 2008
+
+* Large internal rewrite to better support 256 colours and UTF-8. Screen data
+ is now stored as single two-way array of structures rather than as multiple
+ separate arrays. Also simplified a lot of code.
+
+ Only external changes are three new flags, -2, -d and -u, which force tmux to
+ assume the terminal supports 256 colours, default colours (useful for
+ xterm-256color which lacks the AX flag), or UTF-8 respectively.
+
10 September 2008
* Split off colour conversion code from screen code.
@@ -664,4 +674,4 @@
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
-$Id: CHANGES,v 1.160 2008-09-10 18:59:29 nicm Exp $
+$Id: CHANGES,v 1.161 2008-09-25 20:08:51 nicm Exp $
diff --git a/GNUmakefile b/GNUmakefile
index abc13121..b0e9dad3 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile,v 1.39 2008-09-09 22:16:36 nicm Exp $
+# $Id: GNUmakefile,v 1.40 2008-09-25 20:08:51 nicm Exp $
.PHONY: clean
@@ -12,7 +12,9 @@ DATE= $(shell date +%Y%m%d-%H%M)
META?= \002
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
- xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \
+ xmalloc.c xmalloc-debug.c input.c input-keys.c \
+ screen.c screen-write.c screen-redraw.c \
+ grid.c grid-view.c \
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
key-string.c key-bindings.c resize.c arg.c mode-key.c \
cmd.c cmd-generic.c cmd-string.c \
@@ -31,7 +33,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c \
window-scroll.c window-more.c window-copy.c options.c paste.c \
- tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c utf8.c
+ tty.c tty-keys.c tty-write.c colour.c utf8.c
CC?= gcc
INCDIRS+= -I. -I-
diff --git a/Makefile b/Makefile
index 51334ace..2ada4b8d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.74 2008-09-10 18:59:29 nicm Exp $
+# $Id: Makefile,v 1.75 2008-09-25 20:08:51 nicm Exp $
.SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html
@@ -17,7 +17,8 @@ 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 screen-display.c screen-write.c screen-redraw.c \
+ screen.c screen-write.c screen-redraw.c \
+ grid.c grid-view.c \
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
key-string.c key-bindings.c resize.c arg.c mode-key.c \
cmd.c cmd-generic.c cmd-string.c \
diff --git a/TODO b/TODO
index 54311a6f..ac90869c 100644
--- a/TODO
+++ b/TODO
@@ -41,127 +41,10 @@
-- For 0.5 --------------------------------------------------------------------
-XXX
-screen contains grid
-
-screen_write <-- write to TTY and to screen using close-to-ANSI functions
-screen_redraw <-- write areas of screen to TTY
-grid_view <-- write to viewable area of grid
-grid <-- manipulate grid and history
-
-XXX
-grid_view has ox,oy
-XXX
-
-- FINISH UTF8: fix copy and paste
-- SPLIT u_short attr into attr,flags?
-- maybe rethink backend data structure?
- - utf8 can be 1-4 bytes
- - most common is 1 bytes
- - there can be double-width characters which take n bytes but 2 columns on screen
- - they are not only drawn as two characters, they also require two backspaces to remove
-- three operations:
- - simultaneously update screen and ttys
- - redraw screen or section of screen to ttys
- - write to ttys without updating screen
-
----
-NEED to be able to:
- resize screen
- apply ops to both screen and tty simultaneously
- both when parsing input and when eg scrolling history
- draw on the top of the screen without modifying it
- display arbitrary parts of the history
- redraw arbitrary parts of the visible screen
----
-NEVER need to draw into the history
-
-split off grid manip:
- 16-bit characters
- 8-bit flags
- 8-bit attributes
- 8-bit fg colour
- 8-bit bg colour
-
-struct grid_data {
- struct grid_cell **data;
- int *sizes;
-
- int sx;
- int sy;
-
- int hsize;
- int hlimit;
-};
-struct grid_cell {
- u_short data;
- u_char attr;
- u_char flags;
- u_char fg;
- u_char bg;
-};
-const struct grid_default_cell = { 0x20, 0, 0, 8, 8 };
-
-; grid logically split from
-; -hlimit to 0 and 0 to sy
-
-; ALWAYS fill with default
-
-const struct grid_cell *grid_get(int x, int y);
-void grid_set(int x, int y, const struct grid_cell *cell);
-
-void grid_resize()
-void grid_shift() /* shift lines into history */
-
-struct grid_view {
- int ox;
- int oy;
-
- int sx;
- int sy;
-
- struct grid_data *gdata;
- struct grid_view *parent;
-};
-
-struct grid_cell *grid_view_get_cell(int x, int y)
-void grid_view_set_cell(int x, int y, const struct grid_cell *cell);
-
-int grid_view_absolute_x(int x);
-int grid_view_absolute_y(int y);
-
-int grid_view_relative_x(int x);
-int grid_view_relative_y(int y);
-
-void grid_view_delete_lines(int y, int ny)
-void grid_view_insert_lines(int y, int ny)
-void grid_view_clear_lines(int y, int ny)
-void grid_view_fill_lines(int y, int ny, const struct grid_cell *cell)
-
-void grid_view_delete_cells(int x, int y, int nx)
-void grid_view_insert_cells(int x, int y, int nx)
-void grid_view_clear_cells(int x, int y, int nx)
-void grid_view_fill_cells(int x, int nx, const struct grid_cell *cell)
-
-void grid_view_clear_area(int x, int y, int nx, int ny)
-void grid_view_fill_area(int x, int y, int nx, int ny, const struct grid_cell *cell)
-
----
-
-screen has two (both grid_view):
- base and overlay
-
----
-screen_write writes into overlay if it exists and then base, also optionally to tty
-screen_draw draws overlay + base to display
----
-
----
-
-Would it be better to just expand char to 16-bits and use it as an index only
-for >2-byte characters? or - better - don't support entire UTF range? only the BMP?
-this would get rid of UTF table and limits, but still leave double-width character annoyances
-also would double memory usage
+TODO -- 2 fix window-*.c
+ 3 resizing
+ 4 audit for leftover/unused code
+ 5 next phase of tidying
----
21:09 < merdely> NicM: if I run 'tmux attach -t main' and there is no tmux session named main, start a new one.
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index d3cf24c0..d5ae16e2 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-list-windows.c,v 1.23 2008-09-09 22:16:36 nicm Exp $ */
+/* $Id: cmd-list-windows.c,v 1.24 2008-09-25 20:08:52 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -48,6 +48,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
struct winlink *wl;
struct window *w;
+ struct grid_data *gd;
u_int i;
unsigned long long size;
const char *name;
@@ -57,27 +58,23 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
+ gd = w->base.grid;
size = 0;
- for (i = 0; i < w->base.hsize; i++)
- size += w->base.grid_size[i] * 3;
- size += w->base.hsize * (sizeof *w->base.grid_data);
- size += w->base.hsize * (sizeof *w->base.grid_attr);
- size += w->base.hsize * (sizeof *w->base.grid_fg);
- size += w->base.hsize * (sizeof *w->base.grid_bg);
- size += w->base.hsize * (sizeof *w->base.grid_size);
-
+ for (i = 0; i < gd->hsize; i++)
+ size += gd->size[i] * sizeof **gd->data;
+ size += gd->hsize * (sizeof *gd->data);
+ size += gd->hsize * (sizeof *gd->size);
+
if (w->fd != -1)
name = ttyname(w->fd);
else
name = "";
ctx->print(ctx,
- "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes] "
- "[UTF8 table %u/%u]",
+ "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]",
wl->idx, w->name, w->base.title, name,
screen_size_x(&w->base), screen_size_y(&w->base),
- w->base.hsize, w->base.hlimit, size,
- ARRAY_LENGTH(&w->base.utf8_table.array), UTF8_LIMIT);
+ gd->hsize, gd->hlimit, size);
}
if (ctx->cmdclient != NULL)
diff --git a/grid-view.c b/grid-view.c
new file mode 100644
index 00000000..434a2d06
--- /dev/null
+++ b/grid-view.c
@@ -0,0 +1,199 @@
+/* $Id: grid-view.c,v 1.1 2008-09-25 20:08:52 nicm Exp $ */
+
+/*
+ * Copyright (c) 2008 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"
+
+/*
+ * Grid view functions. These work using coordinates relative to the visible
+ * screen area.
+ */
+
+#define grid_view_x(gd, x) (x)
+#define grid_view_y(gd, y) ((gd)->hsize + (y))
+
+/* Get cell for reading. */
+const struct grid_cell *
+grid_view_peek_cell(struct grid_data *gd, u_int px, u_int py)
+{
+ return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
+}
+
+/* Get cell for writing. */
+struct grid_cell *
+grid_view_get_cell(struct grid_data *gd, u_int px, u_int py)
+{
+ return (grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
+}
+
+/* Set cell. */
+void
+grid_view_set_cell(
+ struct grid_data *gd, u_int px, u_int py, const struct grid_cell *gc)
+{
+ grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
+}
+
+/* Clear area. */
+void
+grid_view_clear(struct grid_data *gd, u_int px, u_int py, u_int nx, u_int ny)
+{
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
+
+ px = grid_view_x(gd, px);
+ py = grid_view_y(gd, py);
+
+ grid_clear(gd, px, py, nx, ny);
+}
+
+/* Fill area. */
+void
+grid_view_fill(struct grid_data *gd,
+ const struct grid_cell *gc, u_int px, u_int py, u_int nx, u_int ny)
+{
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
+
+ px = grid_view_x(gd, px);
+ py = grid_view_y(gd, py);
+
+ grid_fill(gd, gc, px, py, nx, ny);
+}
+
+/* Scroll region up. */
+void
+grid_view_scroll_region_up(struct grid_data *gd, u_int rupper, u_int rlower)
+{
+ GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
+
+ if (rupper == 0 && rlower == gd->sy - 1) {
+ grid_scroll_line(gd);
+ return;
+ }
+
+ rupper = grid_view_y(gd, rupper);
+ rlower = grid_view_y(gd, rlower);
+
+ grid_move_lines(gd, rupper, rupper + 1, rlower - rupper);
+}
+
+/* Scroll region down. */
+void
+grid_view_scroll_region_down(struct grid_data *gd, u_int rupper, u_int rlower)
+{
+ GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
+
+ rupper = grid_view_y(gd, rupper);
+ rlower = grid_view_y(gd, rlower);
+
+ grid_move_lines(gd, rupper + 1, rupper, rlower - rupper);
+}
+
+/* Insert lines. */
+void
+grid_view_insert_lines(struct grid_data *gd, u_int py, u_int ny)
+{
+ u_int sy;
+
+ GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
+
+ py = grid_view_y(gd, py);
+
+ sy = grid_view_y(gd, gd->sy);
+
+ grid_move_lines(gd, py + ny, py, sy - py - ny);
+}
+
+/* Insert lines in region. */
+void
+grid_view_insert_lines_region(
+ struct grid_data *gd, u_int rupper, u_int rlower, u_int py, u_int ny)
+{
+ GRID_DEBUG(
+ gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
+
+ rupper = grid_view_y(gd, rupper);
+ rlower = grid_view_y(gd, rlower);
+
+ py = grid_view_y(gd, py);
+
+ grid_move_lines(gd, py + ny, py, (rlower + 1) - py - ny);
+}
+
+/* Delete lines. */
+void
+grid_view_delete_lines(struct grid_data *gd, u_int py, u_int ny)
+{
+ u_int sy;
+
+ GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
+
+ py = grid_view_y(gd, py);
+
+ sy = grid_view_y(gd, gd->sy);
+
+ grid_move_lines(gd, py, py + ny, sy - py - ny);
+}
+
+/* Delete lines inside scroll region. */
+void
+grid_view_delete_lines_region(
+ struct grid_data *gd, u_int rupper, u_int rlower, u_int py, u_int ny)
+{
+ GRID_DEBUG(
+ gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
+
+ rupper = grid_view_y(gd, rupper);
+ rlower = grid_view_y(gd, rlower);
+
+ py = grid_view_y(gd, py);
+
+ grid_move_lines(gd, py, py + ny, (rlower + 1) - py - ny);
+}
+
+/* Insert characters. */
+void
+grid_view_insert_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
+{
+ u_int sx;
+
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
+
+ px = grid_view_x(gd, px);
+
+ sx = grid_view_x(gd, gd->sx);
+
+ grid_move_cells(gd, px + nx, px, py, (sx - 1) - (px + nx));
+}
+
+/* Delete characters. */
+void
+grid_view_delete_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
+{
+ u_int sx;
+
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
+
+ px = grid_view_x(gd, px);
+
+ sx = grid_view_x(gd, gd->sx);
+
+ grid_move_cells(gd, px, px + nx, py, (sx - 1) - (px + nx));
+}
diff --git a/grid.c b/grid.c
new file mode 100644
index 00000000..29e39a16
--- /dev/null
+++ b/grid.c
@@ -0,0 +1,353 @@
+/* $Id: grid.c,v 1.1 2008-09-25 20:08:52 nicm Exp $ */
+
+/*
+ * Copyright (c) 2008 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"
+
+/*
+ * Grid data. This is the basic data structure that represents what is shown on
+ * screen.
+ *
+ * A grid is a grid of cells (struct grid_cell). It is sparse, in that cells
+ * are not allocated until they are written to. The grid is logically split
+ * into history and viewable data with the history starting at row (line) 0 and
+ * extending to (hsize - 1); from hsize to hsize + (sy - 1) is the viewable
+ * data. All functions in this file work on absolute coordinates, grid-view.c
+ * has functions which work on the screen data.
+ */
+
+/* Default grid cell data. */
+const struct grid_cell grid_default_cell = { ' ', 0, 0, 8, 8 };
+
+#define grid_check_x(gd, px) do { \
+ if ((px) >= (gd)->sx) \
+ log_fatalx("x out of range: %u", px); \
+} while (0)
+
+#define grid_check_y(gd, py) do { \
+ if ((py) >= (gd)->hsize + (gd)->sy) \
+ log_fatalx("y out of range: %u", py); \
+} while (0)
+
+#define grid_put_cell(gd, px, py, gc) do { \
+ memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \
+} while (0)
+
+/* Create a new grid. */
+struct grid_data *
+grid_create(u_int sx, u_int sy, u_int hlimit)
+{
+ struct grid_data *gd;
+
+ gd = xmalloc(sizeof *gd);
+ gd->sx = sx;
+ gd->sy = sy;
+
+ gd->hsize = 0;
+ gd->hlimit = hlimit;
+
+ gd->size = xcalloc(gd->sy, sizeof *gd->size);
+ gd->data = xcalloc(gd->sy, sizeof *gd->data);
+
+ return (gd);
+}
+
+/* Destroy grid. */
+void
+grid_destroy(struct grid_data *gd)
+{
+ u_int yy;
+
+ for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
+ if (gd->data[yy] != NULL)
+ xfree(gd->data[yy]);
+ }
+
+ if (gd->data != NULL)
+ xfree(gd->data);
+ if (gd->size != NULL)
+ xfree(gd->size);
+ xfree(gd);
+}
+
+/* Scroll a line into the history. */
+void
+grid_scroll_line(struct grid_data *gd)
+{
+ u_int yy;
+
+ GRID_DEBUG(gd, "");
+
+ if (gd->hsize >= gd->hlimit - 1) {
+ /* If the limit is hit, free the bottom 10% and shift up. */
+ yy = gd->hlimit / 10;
+ if (yy < 1)
+ yy = 1;
+
+ grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
+ gd->hsize -= yy;
+ }
+
+ yy = gd->hsize + gd->sy;
+ gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
+ gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
+
+ gd->data[yy] = NULL;
+ gd->size[yy] = 0;
+
+ gd->hsize++;
+}
+
+/* Reduce line to fit to cell. */
+void
+grid_reduce_line(struct grid_data *gd, u_int py, u_int sx)
+{
+ if (sx >= gd->size[py])
+ return;
+
+ gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
+ gd->size[py] = sx;
+}
+
+/* Expand line to fit to cell. */
+void
+grid_expand_line(struct grid_data *gd, u_int py, u_int sx)
+{
+ u_int xx;
+
+ if (sx <= gd->size[py])
+ return;
+
+ gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
+ for (xx = gd->size[py]; xx < sx; xx++)
+ grid_put_cell(gd, xx, py, &grid_default_cell);
+ gd->size[py] = sx;
+}
+
+/* Get cell for reading. */
+const struct grid_cell *
+grid_peek_cell(struct grid_data *gd, u_int px, u_int py)
+{
+ grid_check_x(gd, px);
+ grid_check_y(gd, py);
+
+ if (px >= gd->size[py])
+ return (&grid_default_cell);
+ return (&gd->data[py][px]);
+}
+
+/* Get cell at relative position (for writing). */
+struct grid_cell *
+grid_get_cell(struct grid_data *gd, u_int px, u_int py)
+{
+ grid_check_x(gd, px);
+ grid_check_y(gd, py);
+
+ grid_expand_line(gd, py, px + 1);
+ return (&gd->data[py][px]);
+}
+
+/* Set cell at relative position. */
+void
+grid_set_cell(
+ struct grid_data *gd, u_int px, u_int py, const struct grid_cell *gc)
+{
+ grid_check_x(gd, px);
+ grid_check_y(gd, py);
+
+ grid_expand_line(gd, py, px + 1);
+ grid_put_cell(gd, px, py, gc);
+}
+
+/*
+ * Clear area. Note this is different from a fill as it just omits unallocated
+ * cells.
+ */
+void
+grid_clear(struct grid_data *gd, u_int px, u_int py, u_int nx, u_int ny)
+{
+ u_int xx, yy;
+
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
+
+ if (nx == 0 || ny == 0)
+ return;
+
+ if (px == 0 && nx == gd->sx) {
+ grid_clear_lines(gd, py, ny);
+ return;
+ }
+
+ grid_check_x(gd, px);
+ grid_check_x(gd, px + nx - 1);
+ grid_check_y(gd, py);
+ grid_check_y(gd, py + ny - 1);
+
+ for (yy = py; yy < py + ny; yy++) {
+ for (xx = px; xx < px + nx; xx++) {
+ if (xx >= gd->size[yy])
+ break;
+ grid_put_cell(gd, xx, yy, &grid_default_cell);
+ }
+ }
+}
+
+/* Fill area. */
+void
+grid_fill(struct grid_data *gd,
+ const struct grid_cell *gc, u_int px, u_int py, u_int nx, u_int ny)
+{
+ u_int xx, yy;
+
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
+
+ if (nx == 0 || ny == 0)
+ return;
+
+ grid_check_x(gd, px);
+ grid_check_x(gd, px + nx - 1);
+ grid_check_y(gd, py);
+ grid_check_y(gd, py + ny - 1);
+
+ for (yy = py; yy < py + ny; yy++) {
+ for (xx = px; xx < px + nx; xx++) {
+ grid_expand_line(gd, yy, xx + 1);
+ grid_put_cell(gd, xx, py, gc);
+ }
+ }
+}
+
+/* Clear lines. This just frees and truncates the lines. */
+void
+grid_clear_lines(struct grid_data *gd, u_int py, u_int ny)
+{
+ u_int yy;
+
+ GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
+
+ if (ny == 0)
+ return;
+
+ grid_check_y(gd, py);
+ grid_check_y(gd, py + ny - 1);
+
+ for (yy = py; yy < py + ny; yy++) {
+ if (gd->data[yy] != NULL) {
+ xfree(gd->data[yy]);
+ gd->data[yy] = NULL;
+ gd->size[yy] = 0;
+ }
+ }
+}
+
+/* Fill a group of lines. */
+void
+grid_fill_lines(
+ struct grid_data *gd, const struct grid_cell *gc, u_int py, u_int ny)
+{
+ grid_fill(gd, gc, 0, py, gd->sx, ny);
+}
+
+/* Move a group of lines. */
+void
+grid_move_lines(struct grid_data *gd, u_int dy, u_int py, u_int ny)
+{
+ u_int yy;
+
+ GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny);
+
+ if (ny == 0 || py == dy)
+ return;
+
+ grid_check_y(gd, py);
+ grid_check_y(gd, py + ny - 1);
+ grid_check_y(gd, dy);
+ grid_check_y(gd, dy + ny - 1);
+
+ /* Free any lines which are being replaced. */
+ for (yy = dy; yy < dy + ny; yy++) {
+ if (yy >= py && yy < py + ny)
+ continue;
+ grid_clear_lines(gd, yy, 1);
+ }
+
+ memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data));
+ memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size));
+
+ /* Wipe any lines that have been moved (without freeing them). */
+ for (yy = py; yy < py + ny; yy++) {
+ if (yy >= dy && yy < dy + ny)
+ continue;
+ gd->data[yy] = NULL;
+ gd->size[yy] = 0;
+ }
+}
+
+/* Clear a group of cells. */
+void
+grid_clear_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
+{
+ u_int xx;
+
+ GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
+
+ if (nx == 0)
+ return;
+
+ grid_check_x(gd, px);
+ grid_check_x(gd, px + nx - 1);
+ grid_check_y(gd, py);
+
+ for (xx = px; xx < px + nx; xx++) {
+ if (xx >= gd->size[py])
+ break;
+ grid_put_cell(gd, xx, py, &grid_default_cell);
+ }
+}
+
+/* Move a group of cells. */
+void
+grid_move_cells(struct grid_data *gd, u_int dx, u_int px, u_int py, u_int nx)
+{
+ u_int xx;
+
+ GRID_DEBUG(gd, "dx=%u, px=%u, py=%u, nx=%u", dx, px, py, nx);
+
+ if (nx == 0 || px == dx)
+ return;
+
+ grid_check_x(gd, px);
+ grid_check_x(gd, px + nx - 1);
+ grid_check_y(gd, py);
+
+ grid_expand_line(gd, py ,px + nx);
+ grid_expand_line(gd, py, dx + nx);
+ memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data));
+
+ /* Wipe any cells that have been moved. */
+ for (xx = px; xx < px + nx; xx++) {
+ if (xx >= dx && xx < dx + nx)
+ continue;
+ memcpy(
+ &gd->data[py][xx], &grid_default_cell, sizeof **gd->data);
+ }
+}
+
diff --git a/input.c b/input.c
index a15f60cb..ada32df1 100644
--- a/input.c
+++ b/input.c
@@ -1,4 +1,4 @@
-/* $Id: input.c,v 1.58 2008-09-09 22:16:36 nicm Exp $ */
+/* $Id: input.c,v 1.59 2008-09-25 20:08:52 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -186,12 +186,20 @@ input_state(struct input_ctx *ictx, void *state)
void
input_init(struct window *w)
{
- ARRAY_INIT(&w->ictx.args);
+ struct input_ctx *ictx = &w->ictx;
+
+ ARRAY_INIT(&ictx->args);
- w->ictx.string_len = 0;
- w->ictx.string_buf = NULL;
+ ictx->string_len = 0;
+ ictx->string_buf = NULL;
- input_state(&w->ictx, input_state_first);
+ memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
+
+ memcpy(&ictx->saved_cell, &grid_default_cell, sizeof ictx->saved_cell);
+ ictx->saved_cx = 0;
+ ictx->saved_cy = 0;
+
+ input_state(ictx, input_state_first);
}
void
@@ -341,10 +349,9 @@ void
input_state_title_next(u_char ch, struct input_ctx *ictx)
{
if (ch == '\007') {
- if (ictx->string_type == STRING_TITLE) {
- screen_write_set_title(
- &ictx->ctx, input_get_string(ictx));
- } else
+ if (ictx->string_type == STRING_TITLE)
+ screen_set_title(ictx->ctx.s, input_get_string(ictx));
+ else
input_abort_string(ictx);
input_state(ictx, input_state_first);
return;
@@ -490,59 +497,67 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
void
input_state_utf8(u_char ch, struct input_ctx *ictx)
{
+ u_int value;
+
log_debug2("-- un %zu: %hhu (%c)", ictx->off, ch, ch);
- ictx->utf8_buf.data[ictx->utf8_off++] = ch;
+ ictx->utf8_buf[ictx->utf8_off++] = ch;
if (--ictx->utf8_len != 0)
return;
input_state(ictx, input_state_first);
- screen_write_put_utf8(&ictx->ctx, &ictx->utf8_buf);
+ value = utf8_combine(ictx->utf8_buf);
+ if (value > 0xffff) /* non-BMP not supported */
+ value = '_';
+
+ ictx->cell.data = value;
+ screen_write_cell(&ictx->ctx, &ictx->cell);
}
void
input_handle_character(u_char ch, struct input_ctx *ictx)
{
- log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
-
if (ch > 0x7f) {
/*
- * UTF8 sequence.
+ * UTF-8 sequence.
*
* 11000010-11011111 C2-DF start of 2-byte sequence
* 11100000-11101111 E0-EF start of 3-byte sequence
* 11110000-11110100 F0-F4 start of 4-byte sequence
*/
- memset(&ictx->utf8_buf.data, 0xff, sizeof &ictx->utf8_buf.data);
- ictx->utf8_buf.data[0] = ch;
+ memset(ictx->utf8_buf, 0xff, sizeof ictx->utf8_buf);
+ ictx->utf8_buf[0] = ch;
ictx->utf8_off = 1;
if (ch >= 0xc2 && ch <= 0xdf) {
- log_debug2(":: u2");
+ log_debug2("-- u2 %zu: %hhu (%c)", ictx->off, ch, ch);
input_state(ictx, input_state_utf8);
ictx->utf8_len = 1;
+ return;
}
if (ch >= 0xe0 && ch <= 0xef) {
- log_debug2(":: u3");
+ log_debug2("-- u3 %zu: %hhu (%c)", ictx->off, ch, ch);
input_state(ictx, input_state_utf8);
ictx->utf8_len = 2;
+ return;
}
if (ch >= 0xf0 && ch <= 0xf4) {
- log_debug2(":: u4");
+ log_debug2("-- u4 %zu: %hhu (%c)", ictx->off, ch, ch);
input_state(ictx, input_state_utf8);
ictx->utf8_len = 3;
+ return;
}
- return;
}
+ log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
- screen_write_put_character(&ictx->ctx, ch);
+ ictx->cell.data = ch;
+ screen_write_cell(&ictx->ctx, &ictx->cell);
}
void
input_handle_c0_control(u_char ch, struct input_ctx *ictx)
{
struct screen *s = ictx->ctx.s;
- u_short attr;
log_debug2("-- c0 %zu: %hhu", ictx->off, ch);
@@ -550,32 +565,31 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx)
case '\0': /* NUL */
break;
case '\n': /* LF */
- screen_write_cursor_down_scroll(&ictx->ctx);
+ screen_write_linefeed(&ictx->ctx);
break;
case '\r': /* CR */
- screen_write_move_cursor(&ictx->ctx, 0, s->cy);
+ screen_write_carriagereturn(&ictx->ctx);
break;
case '\007': /* BELL */
ictx->w->flags |= WINDOW_BELL;
break;
case '\010': /* BS */
- screen_write_cursor_left(&ictx->ctx, 1);
+ screen_write_cursorleft(&ictx->ctx, 1);
break;
case '\011': /* TAB */
+ /* XXX right? */
s->cx = ((s->cx / 8) * 8) + 8;
- if (s->cx > screen_last_x(s)) {
+ if (s->cx > screen_size_x(s) - 1) {
s->cx = 0;
- screen_write_cursor_down(&ictx->ctx, 1);
+ screen_write_cursordown(&ictx->ctx, 1);
}
- screen_write_move_cursor(&ictx->ctx, s->cx, s->cy);
+ screen_write_cursormove(&ictx->ctx, s->cx, s->cy);
break;
case '\016': /* SO */
- attr = s->attr | ATTR_CHARSET;
- screen_write_set_attributes(&ictx->ctx, attr, s->fg, s->bg);
+ ictx->cell.attr |= GRID_ATTR_CHARSET;
break;
case '\017': /* SI */
- attr = s->attr & ~ATTR_CHARSET;
- screen_write_set_attributes(&ictx->ctx, attr, s->fg, s->bg);
+ ictx->cell.attr &= ~GRID_ATTR_CHARSET;
break;
default:
log_debug("unknown c0: %hhu", ch);
@@ -590,7 +604,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx)
switch (ch) {
case 'M': /* RI */
- screen_write_cursor_up_scroll(&ictx->ctx);
+ screen_write_reverseindex(&ictx->ctx);
break;
default:
log_debug("unknown c1: %hhu", ch);
@@ -607,27 +621,22 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx)
switch (ch) {
case '=': /* DECKPAM */
- screen_write_set_mode(&ictx->ctx, MODE_KKEYPAD);
+ screen_write_kkeypadmode(&ictx->ctx, 1);
log_debug("kkeypad on (application mode)");
break;
case '>': /* DECKPNM */
- screen_write_clear_mode(&ictx->ctx, MODE_KKEYPAD);
+ screen_write_kkeypadmode(&ictx->ctx, 0);
log_debug("kkeypad off (number mode)");
break;
case '7': /* DECSC */
- s->saved_cx = s->cx;
- s->saved_cy = s->cy;
- s->saved_attr = s->attr;
- s->saved_fg = s->fg;
- s->saved_bg = s->bg;
- s->mode |= MODE_SAVED;
+ memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
+ ictx->saved_cx = s->cx;
+ ictx->saved_cy = s->cy;
break;
case '8': /* DECRC */
- if (!(s->mode & MODE_SAVED))
- break;
- screen_write_set_attributes(
- &ictx->ctx, s->saved_attr, s->saved_fg, s->saved_bg);
- screen_write_move_cursor(&ictx->ctx, s->saved_cx, s->saved_cy);
+ memcpy(&ictx->cell, &ictx->saved_cell, sizeof ictx->cell);
+ screen_write_cursormove(
+ &ictx->ctx, ictx->saved_cx, ictx->saved_cy);
break;
default:
log_debug("unknown p2: %hhu", ch);
@@ -641,6 +650,21 @@ input_handle_standard_two(u_char ch, struct input_ctx *ictx)
log_debug2("-- s2 %zu: %hhu (%c)", ictx->off, ch, ch);
switch (ch) {
+ case 'c': /* RIS */
+ memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
+
+ memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
+ ictx->saved_cx = 0;
+ ictx->saved_cy = 0;
+
+ screen_write_insertmode(&ictx->ctx, 0);
+ screen_write_kcursormode(&ictx->ctx, 0);
+ screen_write_kkeypadmode(&ictx->ctx, 0);
+ screen_write_mousemode(&ictx->ctx, 0);
+
+ screen_write_clearscreen(&ictx->ctx);
+ screen_write_cursormove(&ictx->ctx, 0, 0);
+ break;
case 'k':
input_start_string(ictx, STRING_NAME);
input_state(ictx, input_state_string_next);
@@ -718,7 +742,7 @@ input_handle_sequence_cuu(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_cursor_up(&ictx->ctx, n);
+ screen_write_cursorup(&ictx->ctx, n);
}
void
@@ -736,7 +760,7 @@ input_handle_sequence_cud(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_cursor_down(&ictx->ctx, n);
+ screen_write_cursordown(&ictx->ctx, n);
}
void
@@ -754,7 +778,7 @@ input_handle_sequence_cuf(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_cursor_right(&ictx->ctx, n);
+ screen_write_cursorright(&ictx->ctx, n);
}
void
@@ -772,7 +796,7 @@ input_handle_sequence_cub(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_cursor_left(&ictx->ctx, n);
+ screen_write_cursorleft(&ictx->ctx, n);
}
void
@@ -790,7 +814,7 @@ input_handle_sequence_dch(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_delete_characters(&ictx->ctx, n);
+ screen_write_deletecharacter(&ictx->ctx, n);
}
void
@@ -808,7 +832,7 @@ input_handle_sequence_dl(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_delete_lines(&ictx->ctx, n);
+ screen_write_deleteline(&ictx->ctx, n);
}
void
@@ -826,7 +850,7 @@ input_handle_sequence_ich(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_insert_characters(&ictx->ctx, n);
+ screen_write_insertcharacter(&ictx->ctx, n);
}
void
@@ -844,7 +868,7 @@ input_handle_sequence_il(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_insert_lines(&ictx->ctx, n);
+ screen_write_insertline(&ictx->ctx, n);
}
void
@@ -863,7 +887,7 @@ input_handle_sequence_vpa(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_move_cursor(&ictx->ctx, s->cx, n - 1);
+ screen_write_cursormove(&ictx->ctx, s->cx, n - 1);
}
void
@@ -882,7 +906,7 @@ input_handle_sequence_hpa(struct input_ctx *ictx)
if (n == 0)
n = 1;
- screen_write_move_cursor(&ictx->ctx, n - 1, s->cy);
+ screen_write_cursormove(&ictx->ctx, n - 1, s->cy);
}
void
@@ -904,7 +928,7 @@ input_handle_sequence_cup(struct input_ctx *ictx)
if (m == 0)
m = 1;
- screen_write_move_cursor(&ictx->ctx, m - 1, n - 1);
+ screen_write_cursormove(&ictx->ctx, m - 1, n - 1);
}
void
@@ -924,10 +948,13 @@ input_handle_sequence_ed(struct input_ctx *ictx)
switch (n) {
case 0:
- screen_write_fill_end_of_screen(&ictx->ctx);
+ screen_write_clearendofscreen(&ictx->ctx);
+ break;
+ case 1:
+ screen_write_clearstartofscreen(&ictx->ctx);
break;
case 2:
- screen_write_fill_screen(&ictx->ctx);
+ screen_write_clearscreen(&ictx->ctx);
break;
}
}
@@ -949,13 +976,13 @@ input_handle_sequence_el(struct input_ctx *ictx)
switch (n) {
case 0:
- screen_write_fill_end_of_line(&ictx->ctx);
+ screen_write_clearendofline(&ictx->ctx);
break;
case 1:
- screen_write_fill_start_of_line(&ictx->ctx);
+ screen_write_clearstartofline(&ictx->ctx);
break;
case 2:
- screen_write_fill_line(&ictx->ctx);
+ screen_write_clearline(&ictx->ctx);
break;
}
}
@@ -973,15 +1000,15 @@ input_handle_sequence_sm(struct input_ctx *ictx)
if (ictx->private == '?') {
switch (n) {
case 1: /* GATM */
- screen_write_set_mode(&ictx->ctx, MODE_KCURSOR);
+ screen_write_kcursormode(&ictx->ctx, 1);
log_debug("kcursor on");
break;
case 25: /* TCEM */
- screen_write_set_mode(&ictx->ctx, MODE_CURSOR);
+ screen_write_cursormode(&ictx->ctx, 1);
log_debug("cursor on");
break;
case 1000:
- screen_write_set_mode(&ictx->ctx, MODE_MOUSE);
+ screen_write_mousemode(&ictx->ctx, 1);
log_debug("mouse on");
break;
default:
@@ -991,7 +1018,7 @@ input_handle_sequence_sm(struct input_ctx *ictx)
} else {
switch (n) {
case 4: /* IRM */
- screen_write_set_mode(&ictx->ctx, MODE_INSERT);
+ screen_write_insertmode(&ictx->ctx, 1);
log_debug("insert on");
break;
case 34:
@@ -1017,15 +1044,15 @@ input_handle_sequence_rm(struct input_ctx *ictx)
if (ictx->private == '?') {
switch (n) {
case 1: /* GATM */
- screen_write_clear_mode(&ictx->ctx, MODE_KCURSOR);
+ screen_write_kcursormode(&ictx->ctx, 0);
log_debug("kcursor off");
break;
case 25: /* TCEM */
- screen_write_clear_mode(&ictx->ctx, MODE_CURSOR);
+ screen_write_cursormode(&ictx->ctx, 0);
log_debug("cursor off");
break;
case 1000:
- screen_write_clear_mode(&ictx->ctx, MODE_MOUSE);
+ screen_write_mousemode(&ictx->ctx, 0);
log_debug("mouse off");
break;
default:
@@ -1035,7 +1062,7 @@ input_handle_sequence_rm(struct input_ctx *ictx)
} else if (ictx->private == '\0') {
switch (n) {
case 4: /* IRM */
- screen_write_clear_mode(&ictx->ctx, MODE_INSERT);
+ screen_write_insertmode(&ictx->ctx, 0);
log_debug("insert off");
break;
case 34:
@@ -1093,118 +1120,107 @@ input_handle_sequence_decstbm(struct input_ctx *ictx)
if (m == 0)
m = screen_size_y(s);
- screen_write_set_region(&ictx->ctx, n - 1, m - 1);
+ screen_write_scrollregion(&ictx->ctx, n - 1, m - 1);
}
void
input_handle_sequence_sgr(struct input_ctx *ictx)
{
- struct screen *s = ictx->ctx.s;
- u_int i, n;
- uint16_t m, o;
- u_short attr;
- u_char fg, bg;
-
- attr = s->attr;
- fg = s->fg;
- bg = s->bg;
-
- n = ARRAY_LENGTH(&ictx->args);
- if (n == 0) {
- attr = 0;
- fg = 8;
- bg = 8;
- } else {
- for (i = 0; i < n; i++) {
- if (input_get_argument(ictx, i, &m, 0) != 0)
- return;
+ struct grid_cell *gc = &ictx->cell;
+ u_int i;
+ uint16_t m, o;
- if (m == 38 || m == 48) {
- i++;
- if (input_get_argument(ictx, i, &o, 0) != 0)
- return;
- if (o != 5)
- continue;
-
- i++;
- if (input_get_argument(ictx, i, &o, 0) != 0)
- return;
- if (m == 38) {
- attr |= ATTR_FG256;
- fg = o;
- } else if (m == 48) {
- attr |= ATTR_BG256;
- bg = o;
- }
+ if (ARRAY_LENGTH(&ictx->args) == 0) {
+ memcpy(gc, &grid_default_cell, sizeof *gc);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
+ if (input_get_argument(ictx, i, &m, 0) != 0)
+ return;
+
+ if (m == 38 || m == 48) {
+ i++;
+ if (input_get_argument(ictx, i, &o, 0) != 0)
+ return;
+ if (o != 5)
continue;
+
+ i++;
+ if (input_get_argument(ictx, i, &o, 0) != 0)
+ return;
+ if (m == 38) {
+ gc->flags |= GRID_FLAG_FG256;
+ gc->fg = o;
+ } else if (m == 48) {
+ gc->flags |= GRID_FLAG_BG256;
+ gc->bg = o;
}
+ continue;
+ }
- switch (m) {
- case 0:
- case 10:
- attr &= ATTR_CHARSET;
- fg = 8;
- bg = 8;
- break;
- case 1:
- attr |= ATTR_BRIGHT;
- break;
- case 2:
- attr |= ATTR_DIM;
- break;
- case 3:
- attr |= ATTR_ITALICS;
- break;
- case 4:
- attr |= ATTR_UNDERSCORE;
- break;
- case 5:
- attr |= ATTR_BLINK;
- break;
- case 7:
- attr |= ATTR_REVERSE;
- break;
- case 8:
- attr |= ATTR_HIDDEN;
- break;
- case 23:
- attr &= ~ATTR_ITALICS;
- break;
- case 24:
- attr &= ~ATTR_UNDERSCORE;
- break;
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- attr &= ~ATTR_FG256;
- fg = m - 30;
- break;
- case 39:
- attr &= ~ATTR_FG256;
- fg = 8;
- break;
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- attr &= ~ATTR_BG256;
- bg = m - 40;
- break;
- case 49:
- attr &= ~ATTR_BG256;
- bg = 8;
- break;
- }
+ switch (m) {
+ case 0:
+ case 10:
+ memcpy(gc, &grid_default_cell, sizeof *gc);
+ break;
+ case 1:
+ gc->attr |= GRID_ATTR_BRIGHT;
+ break;
+ case 2:
+ gc->attr |= GRID_ATTR_DIM;
+ break;
+ case 3:
+ gc->attr |= GRID_ATTR_ITALICS;
+ break;
+ case 4:
+ gc->attr |= GRID_ATTR_UNDERSCORE;
+ break;
+ case 5:
+ gc->attr |= GRID_ATTR_BLINK;
+ break;
+ case 7:
+ gc->attr |= GRID_ATTR_REVERSE;
+ break;
+ case 8:
+ gc->attr |= GRID_ATTR_HIDDEN;
+ break;
+ case 23:
+ gc->attr &= ~GRID_ATTR_ITALICS;
+ break;
+ case 24:
+ gc->attr &= ~GRID_ATTR_UNDERSCORE;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ gc->flags &= ~GRID_FLAG_FG256;
+ gc->fg = m - 30;
+ break;
+ case 39:
+ gc->flags &= ~GRID_FLAG_FG256;
+ gc->fg = 8;
+ break;
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ gc->flags &= ~GRID_FLAG_BG256;
+ gc->bg = m - 40;
+ break;
+ case 49:
+ gc->flags &= ~GRID_FLAG_BG256;
+ gc->bg = 8;
+ break;
}
}
- screen_write_set_attributes(&ictx->ctx, attr, fg, bg);
}
diff --git a/log.c b/log.c
index ac23e301..f81c2bb4 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
-/* $Id: log.c,v 1.5 2008-08-08 17:35:42 nicm Exp $ */
+/* $Id: log.c,v 1.6 2008-09-25 20:08:52 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -224,6 +224,9 @@ log_vfatal(const char *msg, va_list ap)
}
free(fmt);
+#ifdef DEBUG
+ abort();
+#endif
exit(1);
}
diff --git a/screen-display.c b/screen-display.c
deleted file mode 100644
index 4760d8ee..00000000
--- a/screen-display.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/* $Id: screen-display.c,v 1.21 2008-09-09 22:16:36 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"
-
-/* Get a cell. */
-void
-screen_display_get_cell(struct screen *s,
- u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg)
-{
- screen_get_cell(
- s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
-}
-
-/* Set a cell. */
-void
-screen_display_set_cell(struct screen *s,
- u_int px, u_int py, u_char data, u_short attr, u_char fg, u_char bg)
-{
- screen_set_cell(
- s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
-}
-
-/* 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)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- screen_make_lines(s, screen_y(s, py), ny);
- if (s->attr != 0 || s->fg != 8 || s->bg != 8) {
- screen_display_fill_area(
- s, 0, py, screen_size_x(s), ny, ' ', s->attr, s->fg, s->bg);
- }
-}
-
-/* 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)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- 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)) {
- SCREEN_DEBUG3(s, dy, py, ny);
- return;
- }
- if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) {
- SCREEN_DEBUG3(s, dy, py, ny);
- return;
- }
- screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny);
-}
-
-/* Fill a set of cells. */
-void
-screen_display_fill_area(struct screen *s, u_int px, u_int py,
- u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg)
-{
- if (nx == 0 || ny == 0) {
- SCREEN_DEBUG4(s, px, py, nx, ny);
- return;
- }
- if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
- SCREEN_DEBUG4(s, px, py, nx, ny);
- return;
- }
- if (!screen_in_x(s, px + nx - 1) || !screen_in_y(s, py + ny - 1)) {
- SCREEN_DEBUG4(s, px, py, nx, ny);
- return;
- }
- screen_fill_area(
- s, screen_x(s, px), screen_y(s, py), nx, ny, data, attr, fg, bg);
-}
-
-/* Scroll region up. */
-void
-screen_display_scroll_region_up(struct screen *s)
-{
- u_int ny, sy;
-
- /*
- * If the region is the entire screen, this is easy-peasy. Allocate
- * a new line and adjust the history size.
- * XXX should this be done somewhere else?
- */
- if (s->rupper == 0 && s->rlower == screen_last_y(s)) {
- if (s->hsize == s->hlimit) {
- /* If the limit is hit, free 10% and shift up. */
- ny = s->hlimit / 10;
- if (ny < 1)
- ny = 1;
-
- sy = screen_size_y(s) + s->hsize;
- screen_free_lines(s, 0, ny);
- screen_move_lines(s, 0, ny, sy - ny);
-
- s->hsize -= ny;
- }
- s->hsize++;
-
- sy = screen_size_y(s) + s->hsize;
- 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_fg = xrealloc(s->grid_fg, sy, sizeof *s->grid_fg);
- s->grid_bg = xrealloc(s->grid_bg, sy, sizeof *s->grid_fg);
- s->grid_size = xrealloc(s->grid_size, sy, sizeof *s->grid_size);
- screen_display_make_lines(s, screen_last_y(s), 1);
- return;
- }
-
- /*
- * 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);
-}
-
-/* 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);
-}
-
-/* Insert lines. */
-void
-screen_display_insert_lines(struct screen *s, u_int py, u_int ny)
-{
- if (!screen_in_y(s, py)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- if (py + ny > screen_last_y(s))
- ny = screen_size_y(s) - py;
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- /*
- * 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 + ny != screen_size_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)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- if (py + ny > s->rlower)
- ny = (s->rlower + 1) - py;
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- /*
- * 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 + ny != s->rlower + 1) {
- 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)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- if (py + ny > screen_last_y(s))
- ny = screen_size_y(s) - py;
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- /*
- * 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 + ny != screen_size_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)) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
- if (ny == 0) {
- SCREEN_DEBUG2(s, py, ny);
- return;
- }
-
- if (py + ny > s->rlower)
- ny = (s->rlower + 1) - py;
- if (ny == 0)
- return;
-
- /*
- * 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 + ny != s->rlower + 1) {
- 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;
-
- if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
- SCREEN_DEBUG3(s, px, py, nx);
- return;
- }
-
- if (px + nx > screen_last_x(s))
- nx = screen_last_x(s) - px;
-
- py = screen_y(s, py);
-
- /* XXX Cheat and make the line a full line. */
- if (s->grid_size[py] < screen_size_x(s))
- screen_expand_line(s, py, screen_size_x(s));
-
- /*
- * Inserting a range of nx at px.
- *
- * - Move sx - (px + nx) from px to px + nx.
- * - Clear the range at px to px + nx.
- */
-
- 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 * sizeof **s->grid_data);
- memmove(&s->grid_attr[py][px + nx],
- &s->grid_attr[py][px], mx * sizeof **s->grid_attr);
- memmove(&s->grid_fg[py][px + nx],
- &s->grid_fg[py][px], mx * sizeof **s->grid_fg);
- memmove(&s->grid_bg[py][px + nx],
- &s->grid_bg[py][px], mx * sizeof **s->grid_bg);
- }
-
- memset(&s->grid_data[py][px], ' ', nx);
- memset(&s->grid_attr[py][px], s->attr, nx);
- memset(&s->grid_fg[py][px], s->fg, nx);
- memset(&s->grid_bg[py][px], s->bg, nx);
-}
-
-/* Delete characters. */
-void
-screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx)
-{
- u_int mx;
-
- if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
- SCREEN_DEBUG3(s, px, py, nx);
- return;
- }
-
- if (px + nx > screen_last_x(s))
- nx = screen_last_x(s) - px;
-
- py = screen_y(s, py);
-
- /* XXX Cheat and make the line a full line. */
- if (s->grid_size[py] < screen_size_x(s))
- screen_expand_line(s, py, screen_size_x(s));
-
- /*
- * Deleting the range from px to px + nx.
- *
- * - Move sx - (px + nx) from px + nx to px.
- * - Clear the range from sx - nx to sx.
- */
-
- 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_fg[py][px], &s->grid_fg[py][px + nx], mx);
- memmove(&s->grid_bg[py][px], &s->grid_bg[py][px + nx], mx);
- }
-
- memset(&s->grid_data[py][screen_size_x(s) - nx], ' ', nx);
- memset(&s->grid_attr[py][screen_size_x(s) - nx], s->attr, nx);
- memset(&s->grid_fg[py][screen_size_x(s) - nx], s->fg, nx);
- memset(&s->grid_bg[py][screen_size_x(s) - nx], s->bg, nx);
-}
-
-/* Fill cells from another screen, with an offset. */
-void
-screen_display_copy_area(struct screen *dst, struct screen *src,
- u_int px, u_int py, u_int nx, u_int ny, u_int ox, u_int oy)
-{
- u_int i, j;
- u_short attr;
- u_char data, fg, bg;
-
- if (nx == 0 || ny == 0) {
- SCREEN_DEBUG4(dst, px, py, nx, ny);
- return;
- }
- if (!screen_in_x(dst, px) || !screen_in_y(dst, py)) {
- SCREEN_DEBUG4(dst, px, py, nx, ny);
- return;
- }
- if (!screen_in_x(dst, px + nx - 1) || !screen_in_y(dst, py + ny - 1)) {
- SCREEN_DEBUG4(dst, px, py, nx, ny);
- return;
- }
-
- for (i = py; i < py + ny; i++) {
- for (j = px; j < px + nx; j++) {
- screen_get_cell(src,
- screen_x(src, j) + ox, screen_y(src, i) - oy,
- &data, &attr, &fg, &bg);
- screen_display_set_cell(dst, j, i, data, attr, fg, bg);
- }
- }
-}
diff --git a/screen-redraw.c b/screen-redraw.c
index a66aee45..7542d14e 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -1,4 +1,4 @@
-/* $Id: screen-redraw.c,v 1.11 2008-09-08 22:03:54 nicm Exp $ */
+/* $Id: screen-redraw.c,v 1.12 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,9 +22,6 @@
#include "tmux.h"
-void screen_redraw_get_cell(struct screen_redraw_ctx *,
- u_int, u_int, u_char *, u_short *, u_char *, u_char *);
-
/* Initialise redrawing with a window. */
void
screen_redraw_start_window(struct screen_redraw_ctx *ctx, struct window *w)
@@ -66,16 +63,15 @@ screen_redraw_start(struct screen_redraw_ctx *ctx,
* Save screen cursor position. Emulation of some TTY_* commands
* requires this to be correct in the screen, so rather than having
* a local copy and just manipulating it, save the screen's values,
- * modify them during redraw, and restore them when finished.
+ * modify them during redraw, and restore them when finished. XXX.
*/
ctx->saved_cx = s->cx;
ctx->saved_cy = s->cy;
- ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
- ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s));
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
- ctx->write(ctx->data, TTY_CURSOROFF);
- ctx->write(ctx->data, TTY_MOUSEOFF);
+ ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_size_y(s) - 1);
+ ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy);
+ ctx->write(ctx->data, TTY_CURSORMODE, 0);
+ ctx->write(ctx->data, TTY_MOUSEMODE, 0);
}
/* Finish redrawing. */
@@ -87,62 +83,38 @@ screen_redraw_stop(struct screen_redraw_ctx *ctx)
s->cx = ctx->saved_cx;
s->cy = ctx->saved_cy;
- ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy);
if (s->mode & MODE_CURSOR)
- ctx->write(ctx->data, TTY_CURSORON);
+ ctx->write(ctx->data, TTY_CURSORMODE, 1);
if (s->mode & MODE_MOUSE)
- ctx->write(ctx->data, TTY_MOUSEON);
+ ctx->write(ctx->data, TTY_MOUSEMODE, 1);
}
-/* Get cell data. */
+/* Write character. */
void
-screen_redraw_get_cell(struct screen_redraw_ctx *ctx,
- u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg)
+screen_redraw_putc(
+ struct screen_redraw_ctx *ctx, struct grid_cell *gc, u_char ch)
{
- struct screen *s = ctx->s;
-
- screen_get_cell(
- s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
-}
-
-/* Move cursor. */
-void
-screen_redraw_move_cursor(struct screen_redraw_ctx *ctx, u_int px, u_int py)
-{
- if (px != ctx->s->cx || py != ctx->s->cy) {
- ctx->s->cx = px;
- ctx->s->cy = py;
- ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cy, ctx->s->cx);
- }
-}
-
-/* Set attributes. */
-void
-screen_redraw_set_attributes(
- struct screen_redraw_ctx *ctx, u_short attr, u_char fg, u_char bg)
-{
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
+ gc->data = ch;
+ ctx->write(ctx->data, TTY_CELL, gc);
+ ctx->s->cx++;
}
/* Write string. */
-void printflike2
-screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...)
+void printflike3
+screen_redraw_puts(
+ struct screen_redraw_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
{
- va_list ap;
- char *msg, *ptr;
+ va_list ap;
+ char *msg, *ptr;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
- for (ptr = msg; *ptr != '\0'; ptr++) {
- if (*ptr < 0x20)
- continue;
- ctx->write(ctx->data, TTY_CHARACTER, *ptr);
- ctx->s->cx++;
- }
+ for (ptr = msg; *ptr != '\0'; ptr++)
+ screen_redraw_putc(ctx, gc, (u_char) *ptr);
xfree(msg);
}
@@ -151,41 +123,45 @@ screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...)
void
screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py)
{
- u_short attr;
- u_char data, fg, bg;
+ const struct grid_cell *gc;
+ struct grid_cell hc;
- screen_redraw_move_cursor(ctx, px, py);
- screen_redraw_get_cell(ctx, px, py, &data, &attr, &fg, &bg);
-
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
- ctx->write(ctx->data, TTY_CHARACTER, data);
+ if (px != ctx->s->cx || py != ctx->s->cy) {
+ ctx->s->cx = px;
+ ctx->s->cy = py;
+ ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cx, ctx->s->cy);
+ }
+ gc = grid_view_peek_cell(ctx->s->grid, px, py);
+ if (screen_check_selection(ctx->s, px, py)) {
+ memcpy(&hc, gc, sizeof hc);
+ hc.attr |= GRID_ATTR_REVERSE;
+ ctx->write(ctx->data, TTY_CELL, &hc);
+ } else
+ ctx->write(ctx->data, TTY_CELL, gc);
ctx->s->cx++;
}
-/* Redraw area of cells. */
+/* Draw set of lines. */
void
-screen_redraw_area(
- struct screen_redraw_ctx *ctx, u_int px, u_int py, u_int nx, u_int ny)
+screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny)
{
u_int i, j;
- for (i = py; i < py + ny; i++) {
- for (j = px; j < px + nx; j++)
- screen_redraw_cell(ctx, j, i);
+ for (j = py; j < py + ny; j++) {
+ for (i = 0; i < screen_size_x(ctx->s); i++)
+ screen_redraw_cell(ctx, i, j);
}
}
-/* Draw set of lines. */
-void
-screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny)
-{
- screen_redraw_area(ctx, 0, py, screen_size_x(ctx->s), ny);
-}
-
/* Draw set of columns. */
void
screen_redraw_columns(struct screen_redraw_ctx *ctx, u_int px, u_int nx)
{
- screen_redraw_area(ctx, px, 0, nx, screen_size_y(ctx->s));
+ u_int i, j;
+
+ for (j = 0; j < screen_size_y(ctx->s); j++) {
+ for (i = px; i < px + nx; i++)
+ screen_redraw_cell(ctx, i, j);
+ }
}
diff --git a/screen-write.c b/screen-write.c
index 35ac3a59..fa64f2a1 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1,4 +1,4 @@
-/* $Id: screen-write.c,v 1.13 2008-09-09 22:16:36 nicm Exp $ */
+/* $Id: screen-write.c,v 1.14 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,17 +22,6 @@
#include "tmux.h"
-#define screen_write_limit(s, v, lower, upper) do { \
- if (v < lower) { \
- v = lower; \
- SCREEN_DEBUG3(s, v, lower, upper); \
- } \
- if (v > upper) { \
- v = upper; \
- SCREEN_DEBUG3(s, v, lower, upper); \
- } \
-} while (0)
-
/* Initialise writing with a window. */
void
screen_write_start_window(struct screen_write_ctx *ctx, struct window *w)
@@ -71,520 +60,558 @@ screen_write_start(struct screen_write_ctx *ctx,
ctx->s = s;
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSOROFF);
+ ctx->write(ctx->data, TTY_CURSORMODE, 0);
}
-/* Finalise writing. */
+/* Finish writing. */
void
screen_write_stop(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
if (ctx->write != NULL && s->mode & MODE_CURSOR)
- ctx->write(ctx->data, TTY_CURSORON);
+ ctx->write(ctx->data, TTY_CURSORMODE, 1);
}
-/* Set screen title. */
+/* Write character. */
void
-screen_write_set_title(struct screen_write_ctx *ctx, char *title)
+screen_write_putc(
+ struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
{
- struct screen *s = ctx->s;
-
- xfree(s->title);
- s->title = title;
+ gc->data = ch;
+ screen_write_cell(ctx, gc);
}
-/* Put a character. */
-void
-screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
+/* Write string. */
+void printflike3
+screen_write_puts(
+ struct screen_write_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
{
- struct screen *s = ctx->s;
- u_short attr;
-
- if (s->cx == screen_size_x(s)) {
- s->cx = 0;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, '\r');
- screen_write_cursor_down_scroll(ctx);
- } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) {
- SCREEN_DEBUG(s);
- return;
- }
- attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
+ va_list ap;
+ char *msg, *ptr;
- screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
- s->cx++;
+ va_start(ap, fmt);
+ xvasprintf(&msg, fmt, ap);
+ va_end(ap);
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, ch);
+ for (ptr = msg; *ptr != '\0'; ptr++)
+ screen_write_putc(ctx, gc, (u_char) *ptr);
+
+ xfree(msg);
}
-/* Put a UTF8 character. */
+/* Copy from another screen. */
void
-screen_write_put_utf8(struct screen_write_ctx *ctx, struct utf8_data *udat)
+screen_write_copy(struct screen_write_ctx *ctx,
+ struct screen *src, u_int px, u_int py, u_int nx, u_int ny)
{
- struct screen *s = ctx->s;
- u_char ch, ch2, fg, bg;
- u_short attr, attr2;
- int idx, wide;
- u_int n;
-
- wide = 0;
- if (udat->data[2] == 0xff)
- n = ((udat->data[0] & 0x1f)<<6) + (udat->data[1] & 0x3f);
- else if (udat->data[3] == 0xff) {
- n = ((udat->data[0] & 0x0f)<<12) +
- ((udat->data[1] & 0x3f)<<6) + (udat->data[2] & 0x3f);
- } else
- n = 0;
- if ((n >= 0x1100 && n <= 0x115f) || n == 0x2329 || n == 0x232a ||
- (n >= 0x2e80 && n <= 0xa4cf && n != 0x303f) ||
- (n >= 0xac00 && n <= 0xd7a3) || (n >= 0xf900 && n <= 0xfaff) ||
- (n >= 0xfe10 && n <= 0xfe19) || (n >= 0xfe30 && n <= 0xfe6f) ||
- (n >= 0xff00 && n <= 0xff60) || (n >= 0xffe0 && n <= 0xffe6) ||
- (n >= 0x20000 && n <= 0x2fffd) || (n >= 0x30000 && n <= 0x3fffd))
- wide = 1;
-
- if (s->cx >= screen_size_x(s) - wide) {
- s->cx = 0;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CHARACTER, '\r');
- screen_write_cursor_down_scroll(ctx);
- } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) {
- SCREEN_DEBUG(s);
- return;
- }
- attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
-
- if ((idx = utf8_add(&s->utf8_table, udat)) == -1)
- ch = '_';
- else {
- utf8_pack(idx, &ch, &attr);
- attr |= ATTR_UTF8;
- }
-
- /* Remove padding before and after, if any. */
- screen_display_get_cell(s, s->cx, s->cy, &ch2, &attr2, &fg, &bg);
- if (s->cx > 0 && (attr2 & ATTR_PAD))
- screen_display_set_cell(s, s->cx - 1, s->cy, ' ', 0, 8, 8);
- if (s->cx < screen_last_x(s) && (attr2 & ATTR_UTF8)) {
- screen_display_get_cell(
- s, s->cx + 1, s->cy, &ch2, &attr2, &fg, &bg);
- if (s->cx > 0 && (attr2 & ATTR_PAD)) {
- screen_display_set_cell(
- s, s->cx + 1, s->cy, ' ', 0, 8, 8);
+ struct screen *s = ctx->s;
+ struct grid_data *gd = src->grid;
+ const struct grid_cell *gc;
+ u_int xx, yy, cx, cy;
+
+ cx = s->cx;
+ cy = s->cy;
+ for (yy = py; yy < py + ny; yy++) {
+ for (xx = px; xx < px + nx; xx++) {
+ if (xx >= gd->sx || yy >= gd->hsize + gd->sy)
+ gc = &grid_default_cell;
+ else
+ gc = grid_peek_cell(gd, xx, yy);
+ screen_write_cell(ctx, gc);
}
- }
-
- screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
- s->cx++;
-
- if (wide) {
- screen_display_set_cell(s, s->cx, s->cy, ' ', ATTR_PAD, 8, 8);
- s->cx++;
- }
-
- if (ctx->write != NULL) {
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, s->fg, s->bg);
- ctx->write(ctx->data, TTY_CHARACTER, ch);
- ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
+ cy++;
+ screen_write_cursormove(ctx, cx, cy);
}
}
-/* Put a string right-justified. */
-size_t printflike2
-screen_write_put_string_rjust(
- struct screen_write_ctx *ctx, const char *fmt, ...)
+/* Cursor up by ny. */
+void
+screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- va_list ap;
- size_t size;
- char *msg, *ptr;
- va_start(ap, fmt);
- size = vasprintf(&msg, fmt, ap);
- va_end(ap);
+ if (ny > s->cy)
+ ny = s->cy;
+ if (ny == 0)
+ ny = 1;
- ptr = msg;
- if (size > screen_size_x(s)) {
- ptr += size - screen_size_x(s);
- size = screen_size_x(s);
- }
- screen_write_move_cursor(ctx, screen_size_x(s) - size, s->cy);
- for (; *ptr != '\0'; ptr++) {
- if (s->cx == screen_size_x(s))
- break;
- screen_write_put_character(ctx, *ptr);
- }
+ s->cy -= ny;
- xfree(msg);
-
- return (size);
+ if (ctx != NULL)
+ ctx->write(ctx->data, TTY_CURSORUP, ny);
}
-/* Put a string, truncating at end of line. */
-void printflike2
-screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...)
+/* Cursor down by ny. */
+void
+screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- va_list ap;
- char *msg, *ptr;
- va_start(ap, fmt);
- vasprintf(&msg, fmt, ap);
- va_end(ap);
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
+
+ s->cy += ny;
- for (ptr = msg; *ptr != '\0'; ptr++) {
- if (s->cx == screen_size_x(s))
- break;
- screen_write_put_character(ctx, *ptr);
- }
-
- xfree(msg);
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORDOWN, ny);
}
-/* Set screen attributes. */
+/* Cursor right by nx. */
void
-screen_write_set_attributes(
- struct screen_write_ctx *ctx, u_short attr, u_char fg, u_char bg)
+screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
- if (s->attr != attr || s->fg != fg || s->bg != bg) {
- s->attr = attr;
- s->fg = fg;
- s->bg = bg;
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
- if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
- }
+ s->cx += nx;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORRIGHT, nx);
}
-/* Set scroll region. */
+/* Cursor left by nx. */
void
-screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower)
+screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, upper, 0, screen_last_y(s));
- screen_write_limit(s, lower, 0, screen_last_y(s));
- if (upper > lower) {
- SCREEN_DEBUG2(s, upper, lower);
- return;
- }
-
- /* Cursor moves to top-left. */
- s->cx = 0;
- s->cy = upper;
-
- s->rupper = upper;
- s->rlower = lower;
-
+
+ if (nx > s->cx)
+ nx = s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ s->cx -= nx;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
+ ctx->write(ctx->data, TTY_CURSORLEFT, nx);
}
-/* Move cursor up and scroll if necessary. */
+/* Insert nx characters. */
void
-screen_write_cursor_up_scroll(struct screen_write_ctx *ctx)
+screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- if (s->cy == s->rupper)
- screen_display_scroll_region_down(s);
- else if (s->cy > 0)
- s->cy--;
-
+
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_REVERSEINDEX);
+ ctx->write(ctx->data, TTY_INSERTCHARACTER, nx);
}
-/* Move cursor down and scroll if necessary */
+/* Delete nx characters. */
void
-screen_write_cursor_down_scroll(struct screen_write_ctx *ctx)
+screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
-
- if (s->cy == s->rlower)
- screen_display_scroll_region_up(s);
- else if (s->cy < screen_last_y(s))
- s->cy++;
-
- if (ctx->write != NULL) /* XXX FORWARDINDEX */
- ctx->write(ctx->data, TTY_CHARACTER, '\n');
+
+ if (nx > screen_size_x(s) - 1 - s->cx)
+ nx = screen_size_x(s) - 1 - s->cx;
+ if (nx == 0)
+ nx = 1;
+
+ grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_DELETECHARACTER, nx);
}
-/* Move cursor up. */
+/* Insert ny lines. */
void
-screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n)
+screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- screen_write_limit(s, n, 1, screen_above_y(s, s->cy) - 1);
-
- s->cy -= n;
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
+ if (s->cy < s->rupper || s->cy > s->rlower)
+ grid_view_insert_lines(s->grid, s->cy, ny);
+ else {
+ grid_view_insert_lines_region(
+ s->grid, s->rupper, s->rlower, s->cy, ny);
+ }
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_INSERTLINE, ny);
}
-/* Move cursor down. */
+/* Delete ny lines. */
void
-screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n)
+screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy) - 1);
+ if (ny > screen_size_y(s) - 1 - s->cy)
+ ny = screen_size_y(s) - 1 - s->cy;
+ if (ny == 0)
+ ny = 1;
- s->cy += n;
+ if (s->cy < s->rupper || s->cy > s->rlower)
+ grid_view_delete_lines(s->grid, s->cy, ny);
+ else {
+ grid_view_delete_lines_region(
+ s->grid, s->rupper, s->rlower, s->cy, ny);
+ }
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_DELETELINE, ny);
}
-/* Move cursor left. */
+/* Clear line at cursor. */
void
-screen_write_cursor_left(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_left_x(s, s->cx) - 1);
-
- s->cx -= n;
-
+
+ grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_CLEARLINE);
}
-/* Move cursor right. */
+/* Clear to end of line from cursor. */
void
-screen_write_cursor_right(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearendofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx) - 1);
-
- s->cx += n;
-
+
+ grid_view_clear(s->grid, s->cx, s->cy, screen_size_x(s) - s->cx, 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_CLEARENDOFLINE);
}
-/* Delete lines. */
+/* Clear to start of line from cursor. */
void
-screen_write_delete_lines(struct screen_write_ctx *ctx, u_int n)
+screen_write_clearstartofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
+
+ grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CLEARSTARTOFLINE);
+}
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy));
+/* Move cursor to px,py. */
+void
+screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
+{
+ struct screen *s = ctx->s;
+
+ if (px > screen_size_x(s) - 1)
+ px = screen_size_x(s) - 1;
+ if (py > screen_size_y(s) - 1)
+ py = screen_size_y(s) - 1;
+
+ s->cx = px;
+ s->cy = py;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CURSORMOVE, px, py);
+}
- if (s->cy < s->rupper || s->cy > s->rlower)
- screen_display_delete_lines(s, s->cy, n);
+/* Set cursor mode. */
+void
+screen_write_cursormode(struct screen_write_ctx *ctx, int state)
+{
+ struct screen *s = ctx->s;
+
+ if (state)
+ s->mode |= MODE_CURSOR;
else
- screen_display_delete_lines_region(s, s->cy, n);
-
+ s->mode &= ~MODE_CURSOR;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_DELETELINE, n);
+ ctx->write(ctx->data, TTY_CURSORMODE, state);
}
-/* Delete characters. */
+/* Reverse index (up with scroll). */
void
-screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n)
+screen_write_reverseindex(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
+
+ if (s->cy == s->rupper)
+ grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
+ else if (s->cy > 0)
+ s->cy--;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_REVERSEINDEX);
+}
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx));
+/* Set scroll region. */
+void
+screen_write_scrollregion(
+ struct screen_write_ctx *ctx, u_int rupper, u_int rlower)
+{
+ struct screen *s = ctx->s;
+
+ if (rupper > screen_size_y(s) - 1)
+ rupper = screen_size_y(s) - 1;
+ if (rlower > screen_size_y(s) - 1)
+ rlower = screen_size_y(s) - 1;
+ if (rupper > rlower)
+ return;
- screen_display_delete_characters(s, s->cx, s->cy, n);
+ /* Cursor moves to top-left. */
+ s->cx = 0;
+ s->cy = rupper;
+ s->rupper = rupper;
+ s->rlower = rlower;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_DELETECHARACTER, n);
+ ctx->write(ctx->data, TTY_SCROLLREGION, rupper, rlower);
}
-/* Insert lines. */
+/* Set insert mode. */
void
-screen_write_insert_lines(struct screen_write_ctx *ctx, u_int n)
+screen_write_insertmode(struct screen_write_ctx *ctx, int state)
{
struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_below_y(s, s->cy));
-
- if (s->cy < s->rupper || s->cy > s->rlower)
- screen_display_insert_lines(s, s->cy, n);
+
+ if (state)
+ s->mode |= MODE_INSERT;
else
- screen_display_insert_lines_region(s, s->cy, n);
-
+ s->mode &= ~MODE_INSERT;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_INSERTLINE, n);
+ ctx->write(ctx->data, TTY_INSERTMODE, state);
}
-/* Insert characters. */
+/* Set mouse mode. */
void
-screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n)
+screen_write_mousemode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 1, screen_right_x(s, s->cx));
-
- screen_display_insert_characters(s, s->cx, s->cy, n);
+ struct screen *s = ctx->s;
+ if (state)
+ s->mode |= MODE_MOUSE;
+ else
+ s->mode &= ~MODE_MOUSE;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_INSERTCHARACTER, n);
+ ctx->write(ctx->data, TTY_MOUSEMODE, state);
}
-/* Move the cursor. */
+/* Line feed (down with scroll). */
void
-screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m)
+screen_write_linefeed(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
-
- screen_write_limit(s, n, 0, screen_last_x(s));
- screen_write_limit(s, m, 0, screen_last_y(s));
-
- s->cx = n;
- s->cy = m;
-
+ struct screen *s = ctx->s;
+
+ if (s->cy == s->rlower)
+ grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
+ else if (s->cy < screen_size_x(s) - 1)
+ s->cy++;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
+ ctx->write(ctx->data, TTY_LINEFEED);
}
-/* Full to end of screen. */
+/* Carriage return (cursor to start of line). */
void
-screen_write_fill_end_of_screen(struct screen_write_ctx *ctx)
+screen_write_carriagereturn(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- u_int i;
-
- screen_display_fill_area(s, s->cx, s->cy,
- screen_right_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
- screen_display_fill_area(s, 0, s->cy + 1, screen_size_x(s),
- screen_below_y(s, s->cy + 1), ' ', s->attr, s->fg, s->bg);
+ struct screen *s = ctx->s;
+
+ s->cx = 0;
- if (ctx->write != NULL) {
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- for (i = s->cy + 1; i < screen_size_y(s); i++) {
- ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- }
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
- }
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CARRIAGERETURN);
}
-/* Fill entire screen. */
+/* Set keypad cursor keys mode. */
void
-screen_write_fill_screen(struct screen_write_ctx *ctx)
+screen_write_kcursormode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
- u_int i;
-
- screen_display_fill_area(s, 0, 0,
- screen_size_x(s), screen_size_y(s), ' ', s->attr, s->fg, s->bg);
-
- if (ctx->write != NULL) {
- for (i = 0; i < screen_size_y(s); i++) {
- ctx->write(ctx->data, TTY_CURSORMOVE, i, 0);
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
- }
- ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
- }
+ struct screen *s = ctx->s;
+
+ if (state)
+ s->mode |= MODE_KCURSOR;
+ else
+ s->mode &= ~MODE_KCURSOR;
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_KCURSORMODE);
}
-/* Fill to end of line. */
+/* Set keypad number keys mode. */
void
-screen_write_fill_end_of_line(struct screen_write_ctx *ctx)
+screen_write_kkeypadmode(struct screen_write_ctx *ctx, int state)
{
- struct screen *s = ctx->s;
-
- screen_display_fill_area(s, s->cx, s->cy,
- screen_right_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
+ struct screen *s = ctx->s;
+ if (state)
+ s->mode |= MODE_KKEYPAD;
+ else
+ s->mode &= ~MODE_KKEYPAD;
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARENDOFLINE);
+ ctx->write(ctx->data, TTY_KKEYPADMODE);
}
-/* Fill to start of line. */
+/* Clear to end of screen from cursor. */
void
-screen_write_fill_start_of_line(struct screen_write_ctx *ctx)
+screen_write_clearendofscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ u_int sx, sy;
- screen_display_fill_area(s, 0, s->cy,
- screen_left_x(s, s->cx), 1, ' ', s->attr, s->fg, s->bg);
+ sx = screen_size_x(s);
+ sy = screen_size_y(s);
+ grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARSTARTOFLINE);
+ ctx->write(ctx->data, TTY_CLEARENDOFSCREEN);
}
-/* Fill entire line. */
+/* Clear to start of screen. */
void
-screen_write_fill_line(struct screen_write_ctx *ctx)
+screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ u_int sx, sy;
- screen_display_fill_area(
- s, 0, s->cy, screen_size_x(s), s->cy, ' ', s->attr, s->fg, s->bg);
+ sx = screen_size_x(s);
+ sy = screen_size_y(s);
+ if (s->cy > 0)
+ grid_view_clear(s->grid, 0, 0, sx, s->cy - 1);
+ grid_view_clear(s->grid, 0, s->cy, s->cx, 1);
+
if (ctx->write != NULL)
- ctx->write(ctx->data, TTY_CLEARLINE);
+ ctx->write(ctx->data, TTY_CLEARSTARTOFSCREEN);
}
-/* Set a screen mode. */
+/* Clear entire screen. */
void
-screen_write_set_mode(struct screen_write_ctx *ctx, int mode)
+screen_write_clearscreen(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
-
- s->mode |= mode;
-
- if (ctx->write == NULL)
- return;
+ struct screen *s = ctx->s;
- if (mode & MODE_INSERT)
- ctx->write(ctx->data, TTY_INSERTON);
- if (mode & MODE_MOUSE)
- ctx->write(ctx->data, TTY_MOUSEON);
+ grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+
+ if (ctx->write != NULL)
+ ctx->write(ctx->data, TTY_CLEARSCREEN);
}
-/* Clear a screen mode. */
+/* Write cell data. */
void
-screen_write_clear_mode(struct screen_write_ctx *ctx, int mode)
+screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{
- struct screen *s = ctx->s;
+ struct screen *s = ctx->s;
+ struct grid_data *gd = s->grid;
+ u_int width, xx;
+ const struct grid_cell *hc;
+ struct grid_cell *ic, tc;
- s->mode &= ~mode;
+ width = utf8_width(gc->data);
- if (ctx->write == NULL)
- return;
+ /* If the character is wider than the screen, don't print it. */
+ if (width > screen_size_x(s)) {
+ memcpy(&tc, gc, sizeof tc);
+ tc.data = '_';
- if (mode & MODE_INSERT)
- ctx->write(ctx->data, TTY_INSERTOFF);
- if (mode & MODE_MOUSE)
- ctx->write(ctx->data, TTY_MOUSEOFF);
-}
+ width = 1;
+ gc = &tc;
+ }
+
+ /* Check this will fit on the current line; scroll if not. */
+ if (s->cx >= screen_size_x(s) + 1 - width) {
+ screen_write_carriagereturn(ctx);
+ screen_write_linefeed(ctx);
+ }
-/* Copy cells from another screen. */
-void
-screen_write_copy_area(struct screen_write_ctx *ctx,
- struct screen *src, u_int nx, u_int ny, u_int ox, u_int oy)
-{
- struct screen *s = ctx->s;
- struct screen_redraw_ctx rctx;
- int saved_mode;
+ /* Sanity checks. */
+ if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
+ return;
- screen_write_limit(s, nx, 1, screen_right_x(s, s->cx));
- screen_write_limit(s, ny, 1, screen_below_y(s, s->cy));
+ /*
+ * UTF-8 wide characters are a bit of an annoyance. They take up more
+ * than one cell on the screen, so following cells must not be drawn by
+ * marking them as padding.
+ *
+ * So far, so good. The problem is, when overwriting a padding cell, or
+ * a UTF-8 character, it is necessary to also overwrite any other cells
+ * which covered by the same character.
+ */
+ hc = grid_view_peek_cell(gd, s->cx, s->cy);
+ if (hc->flags & GRID_FLAG_PADDING) {
+ /*
+ * A padding cell, so clear any following and leading padding
+ * cells back to the character. Don't overwrite the current
+ * cell as that happens later anyway.
+ */
+ xx = s->cx;
+ while (xx-- > 0) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
- screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy);
+ /* Overwrite the character at the start of this padding. */
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
- if (ctx->write != NULL) {
- /* Save mode XXX hack */
- saved_mode = ctx->s->mode;
- ctx->s->mode &= ~MODE_CURSOR;
+ /* Overwrite following padding cells. */
+ xx = s->cx;
+ while (++xx < screen_size_x(s)) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
+ } else if (utf8_width(hc->data) > 1) {
+ /*
+ * An UTF-8 wide cell; overwrite following padding cells only.
+ */
+ xx = s->cx;
+ while (++xx < screen_size_x(s)) {
+ hc = grid_view_peek_cell(gd, xx, s->cy);
+ if (!(hc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
+ }
+ }
- screen_redraw_start(&rctx, ctx->s, ctx->write, ctx->data);
- screen_redraw_area(&rctx, s->cx, s->cy, nx, ny);
- screen_redraw_stop(&rctx);
+ /*
+ * If the new character is UTF-8 wide, fill in padding cells. Have
+ * already ensured there is enough room.
+ */
+ for (xx = s->cx + 1; xx < s->cx + width; xx++) {
+ ic = grid_view_get_cell(gd, xx, s->cy);
+ ic->flags |= GRID_FLAG_PADDING;
+ }
- ctx->s->mode = saved_mode;
+ /* Write the actual cell. */
+ grid_view_set_cell(gd, s->cx, s->cy, gc);
+ s->cx += width;
+
+ if (ctx->write != NULL) {
+ if (screen_check_selection(ctx->s, s->cx, s->cy)) {
+ memcpy(&tc, gc, sizeof tc);
+ tc.attr |= GRID_ATTR_REVERSE;
+ ctx->write(ctx->data, TTY_CELL, &tc);
+ } else
+ ctx->write(ctx->data, TTY_CELL, gc);
}
}
diff --git a/screen.c b/screen.c
index de643ab0..d85eb676 100644
--- a/screen.c
+++ b/screen.c
@@ -1,4 +1,4 @@
-/* $Id: screen.c,v 1.71 2008-09-10 19:15:04 nicm Exp $ */
+/* $Id: screen.c,v 1.72 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,90 +22,18 @@
#include "tmux.h"
-/*
- * Virtual screen.
- *
- * A screen is stored as three arrays of lines of 8-bit values, one for the
- * actual characters (data), one for attributes and one for colours. Three
- * seperate blocks means memset and friends can be used. Each array is y by x
- * in size, row then column order. Sizes are 0-based. There is an additional
- * array of u_ints with the size of each line.
- *
- * Each screen has a history starting at the beginning of the arrays and
- * extending for hsize lines. Beyond that is the screen display of size
- * dy:
- *
- * ----------- array base
- * | |
- * | history |
- * ----------- array base + hsize
- * | |
- * | display |
- * | |
- * ----------- array base + hsize + dy
- *
- * The screen_x/screen_y macros are used to convert a cell on the displayed
- * area to an absolute position in the arrays.
- *
- * Screen handling code is split into four files:
- *
- * screen.c: Creation/deletion, utility functions, and basic functions to
- * manipulate the screen based on offsets from the base.
- * screen-display.c: Basic functions for manipulating the displayed
- * part of the screen. x,y coordinates passed to these
- * are relative to the display. These are largely
- * utility functions for screen-write.c.
- * screen-redraw.c: Functions for redrawing all or part of a screen to
- * one or more ttys. A context is filled via one of the
- * screen_redraw_start* variants which sets up (removes
- * cursor etc) and figures out which tty_write_* function
- * to use to write to the terminals, then the other
- * screen_redraw_* functions are used to draw the screen,
- * and screen_redraw_stop used to reset the cursor and
- * clean up. These are used when changing window and a
- * few other bits (status line).
- * screen-write.c: Functions for modifying (writing into) the screen and
- * optionally simultaneously updating one or more ttys.
- * These are used in much the same way as the redraw
- * functions. These are used to update when parsing
- * input from the window (input.c) and for the various
- * other modes which maintain private screens.
- *
- * If you're thinking this all seems too complicated, that's because it is :-/.
- */
+void screen_resize_x(struct screen *, u_int);
+void screen_resize_y(struct screen *, u_int);
/* Create a new screen. */
void
-screen_init(struct screen *s, u_int dx, u_int dy, u_int hlimit)
+screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
{
- s->dx = dx;
- s->dy = dy;
- s->cx = 0;
- s->cy = 0;
+ s->grid = grid_create(sx, sy, hlimit);
- s->rupper = 0;
- s->rlower = s->dy - 1;
-
- s->hsize = 0;
- s->hlimit = hlimit;
-
- s->attr = 0;
- s->fg = 8;
- s->bg = 8;
-
- s->mode = MODE_CURSOR;
s->title = xstrdup("");
- s->grid_data = xmalloc(dy * (sizeof *s->grid_data));
- s->grid_attr = xmalloc(dy * (sizeof *s->grid_attr));
- s->grid_fg = xmalloc(dy * (sizeof *s->grid_fg));
- s->grid_bg = xmalloc(dy * (sizeof *s->grid_bg));
- s->grid_size = xmalloc(dy * (sizeof *s->grid_size));
- screen_make_lines(s, 0, dy);
-
- utf8_init(&s->utf8_table, UTF8_LIMIT);
-
- screen_clear_selection(s);
+ screen_reinit(s);
}
/* Reinitialise screen. */
@@ -116,16 +44,13 @@ screen_reinit(struct screen *s)
s->cy = 0;
s->rupper = 0;
- s->rlower = s->dy - 1;
-
- s->attr = 0;
- s->fg = 8;
- s->bg = 8;
+ s->rlower = screen_size_y(s) - 1;
s->mode = MODE_CURSOR;
- screen_display_fill_area(s, 0, 0,
- screen_size_x(s), screen_size_y(s), ' ', 0, 8, 8);
+ /* XXX */
+ grid_clear_lines(
+ s->grid, s->grid->hsize, s->grid->hsize + s->grid->sy - 1);
screen_clear_selection(s);
}
@@ -134,245 +59,121 @@ screen_reinit(struct screen *s)
void
screen_free(struct screen *s)
{
- utf8_free(&s->utf8_table);
xfree(s->title);
- screen_free_lines(s, 0, s->dy + s->hsize);
- xfree(s->grid_data);
- xfree(s->grid_attr);
- xfree(s->grid_fg);
- xfree(s->grid_bg);
- xfree(s->grid_size);
+ grid_destroy(s->grid);
+}
+
+/* Set screen title. */
+void
+screen_set_title(struct screen *s, const char *title)
+{
+ xfree(s->title);
+ s->title = xstrdup(title);
}
/* Resize screen. */
void
screen_resize(struct screen *s, u_int sx, u_int sy)
{
- u_int i, ox, oy, ny, my;
-
if (sx < 1)
sx = 1;
if (sy < 1)
sy = 1;
- ox = s->dx;
- oy = s->dy;
- if (sx == ox && sy == oy)
+ if (sx != screen_size_x(s))
+ screen_resize_x(s, sx);
+ if (sy != screen_size_y(s))
+ screen_resize_y(s, sy);
+}
+
+void
+screen_resize_x(struct screen *s, u_int sx)
+{
+ struct grid_data *gd = s->grid;
+ const struct grid_cell *gc;
+ u_int xx, yy;
+
+ /* If getting larger, not much to do. */
+ if (sx > screen_size_x(s)) {
+ gd->sx = sx;
return;
+ }
- /*
- * X dimension.
- */
- if (sx != ox) {
+ /* If getting smaller, nuke any data in lines over the new size. */
+ for (yy = gd->hsize; yy < gd->hsize + screen_size_y(s); yy++) {
/*
- * If getting smaller, nuke any data in lines over the new
- * size.
+ * If the character after the last is wide or padding, remove
+ * it and any leading padding.
*/
- if (sx < ox) {
- for (i = s->hsize; i < s->hsize + oy; i++) {
- if (s->grid_size[i] > sx)
- screen_reduce_line(s, i, sx);
- }
+ for (xx = sx; xx > 0; xx--) {
+ gc = grid_peek_cell(gd, xx - 1, yy);
+ if (!(gc->flags & GRID_FLAG_PADDING))
+ break;
+ grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
}
+ if (xx > 0 && xx != sx && utf8_width(gc->data) != 1)
+ grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
- if (s->cx >= sx)
- s->cx = sx - 1;
- s->dx = sx;
+ /* Reduce the line size. */
+ grid_reduce_line(gd, yy, sx);
}
- /*
- * Y dimension.
- */
- if (sy == oy)
- return;
+ if (s->cx >= sx)
+ s->cx = sx - 1;
+ gd->sx = sx;
+}
+
+void
+screen_resize_y(struct screen *s, u_int sy)
+{
+ struct grid_data *gd = s->grid;
+ u_int oy, yy, ny;
/* Size decreasing. */
- if (sy < oy) {
- ny = oy - sy;
+ if (sy < screen_size_y(s)) {
+ oy = screen_size_y(s);
+
if (s->cy != 0) {
/*
* The cursor is not at the start. Try to remove as
* many lines as possible from the top. (Up to the
* cursor line.)
*/
- my = s->cy;
- if (my > ny)
- my = ny;
+ ny = s->cy;
+ if (ny > oy - sy)
+ ny = oy - sy;
- screen_free_lines(s, s->hsize, my);
- screen_move_lines(s, s->hsize, s->hsize + my, oy - my);
+ grid_view_delete_lines(gd, 0, ny);
- s->cy -= my;
- oy -= my;
+ s->cy -= ny;
+ oy -= ny;
}
- ny = oy - sy;
- if (ny > 0) {
- /*
- * Remove any remaining lines from the bottom.
- */
- screen_free_lines(s, s->hsize + oy - ny, ny);
+ if (sy < oy) {
+ /* Remove any remaining lines from the bottom. */
+ grid_view_delete_lines(gd, sy, oy - sy);
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_fg = xrealloc(s->grid_fg, ny, sizeof *s->grid_fg);
- s->grid_bg = xrealloc(s->grid_bg, ny, sizeof *s->grid_bg);
- s->grid_size = xrealloc(s->grid_size, ny, sizeof *s->grid_size);
- s->dy = sy;
+ gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size);
+ gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data);
/* Size increasing. */
- if (sy > oy)
- screen_make_lines(s, s->hsize + oy, sy - oy);
-
- s->rupper = 0;
- s->rlower = s->dy - 1;
-}
-
-/* Expand line. */
-void
-screen_expand_line(struct screen *s, u_int py, u_int nx)
-{
- u_int ox;
-
- ox = s->grid_size[py];
- s->grid_size[py] = nx;
-
- s->grid_data[py] = xrealloc(
- s->grid_data[py], sizeof **s->grid_data, nx);
- memset(&s->grid_data[py][ox], ' ', (nx - ox) * sizeof **s->grid_data);
- s->grid_attr[py] = xrealloc(
- s->grid_attr[py], sizeof **s->grid_attr, nx);
- memset(&s->grid_attr[py][ox], 0, (nx - ox) * sizeof **s->grid_attr);
- s->grid_fg[py] = xrealloc(
- s->grid_fg[py], sizeof **s->grid_fg, nx);
- memset(&s->grid_fg[py][ox], 8, (nx - ox) * sizeof **s->grid_fg);
- s->grid_bg[py] = xrealloc(
- s->grid_bg[py], sizeof **s->grid_bg, nx);
- memset(&s->grid_bg[py][ox], 8, (nx - ox) * sizeof **s->grid_bg);
-}
-
-/* Reduce line. */
-void
-screen_reduce_line(struct screen *s, u_int py, u_int nx)
-{
- s->grid_size[py] = nx;
-
- s->grid_data[py] = xrealloc(
- s->grid_data[py], sizeof **s->grid_data, nx);
- s->grid_attr[py] = xrealloc(
- s->grid_attr[py], sizeof **s->grid_attr, nx);
- s->grid_fg[py] = xrealloc(
- s->grid_fg[py], sizeof **s->grid_fg, nx);
- s->grid_bg[py] = xrealloc(
- s->grid_bg[py], sizeof **s->grid_bg, nx);
-}
-
-/* Get cell. */
-void
-screen_get_cell(struct screen *s,
- u_int cx, u_int cy, u_char *data, u_short *attr, u_char *fg, u_char *bg)
-{
- if (cx >= s->grid_size[cy]) {
- *data = ' ';
- *attr = 0;
- *fg = 8;
- *bg = 8;
- } else {
- *data = s->grid_data[cy][cx];
- *attr = s->grid_attr[cy][cx];
- *fg = s->grid_fg[cy][cx];
- *bg = s->grid_bg[cy][cx];
- }
-
- if (screen_check_selection(s, cx, cy))
- *attr |= ATTR_REVERSE;
-}
-
-/* Set a cell. */
-void
-screen_set_cell(struct screen *s,
- u_int cx, u_int cy, u_char data, u_short attr, u_char fg, u_char bg)
-{
- if (cx >= s->grid_size[cy])
- screen_expand_line(s, cy, cx + 1);
-
- s->grid_data[cy][cx] = data;
- s->grid_attr[cy][cx] = attr;
- s->grid_fg[cy][cx] = fg;
- s->grid_bg[cy][cx] = bg;
-}
-
-/* Create a range of lines. */
-void
-screen_make_lines(struct screen *s, u_int py, u_int ny)
-{
- u_int i;
-
- for (i = py; i < py + ny; i++) {
- s->grid_data[i] = NULL;
- s->grid_attr[i] = NULL;
- s->grid_fg[i] = NULL;
- s->grid_bg[i] = NULL;
- s->grid_size[i] = 0;
- }
-}
-
-/* Free a range of ny lines at py. */
-void
-screen_free_lines(struct screen *s, u_int py, u_int ny)
-{
- u_int i;
-
- for (i = py; i < py + ny; i++) {
- if (s->grid_data[i] != NULL)
- xfree(s->grid_data[i]);
- s->grid_data[i] = NULL;
- if (s->grid_attr[i] != NULL)
- xfree(s->grid_attr[i]);
- s->grid_attr[i] = NULL;
- if (s->grid_fg[i] != NULL)
- xfree(s->grid_fg[i]);
- s->grid_fg[i] = NULL;
- if (s->grid_bg[i] != NULL)
- xfree(s->grid_bg[i]);
- s->grid_bg[i] = NULL;
- s->grid_size[i] = 0;
+ if (sy > screen_size_y(s)) {
+ oy = screen_size_y(s);
+ for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) {
+ gd->size[yy] = 0;
+ gd->data[yy] = NULL;
+ }
}
-}
-
-/* Move a range of lines. */
-void
-screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny)
-{
- memmove(
- &s->grid_data[dy], &s->grid_data[py], ny * (sizeof *s->grid_data));
- memmove(
- &s->grid_attr[dy], &s->grid_attr[py], ny * (sizeof *s->grid_attr));
- memmove(
- &s->grid_fg[dy], &s->grid_fg[py], ny * (sizeof *s->grid_fg));
- memmove(
- &s->grid_bg[dy], &s->grid_bg[py], ny * (sizeof *s->grid_bg));
- memmove(
- &s->grid_size[dy], &s->grid_size[py], ny * (sizeof *s->grid_size));
-}
-/* Fill an area. */
-void
-screen_fill_area(struct screen *s, u_int px, u_int py,
- u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg)
-{
- u_int i, j;
-
- for (i = py; i < py + ny; i++) {
- for (j = px; j < px + nx; j++)
- screen_set_cell(s, j, i, data, attr, fg, bg);
- }
+ gd->sy = sy;
+
+ s->rupper = 0;
+ s->rlower = screen_size_y(s) - 1;
}
/* Set selection. */
diff --git a/server-msg.c b/server-msg.c
index f7dfe2bb..65d90f52 100644
--- a/server-msg.c
+++ b/server-msg.c
@@ -1,4 +1,4 @@
-/* $Id: server-msg.c,v 1.50 2008-09-09 22:16:37 nicm Exp $ */
+/* $Id: server-msg.c,v 1.51 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -189,6 +189,10 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c)
tty_init(&c->tty, data.tty, xstrdup(term));
if (data.flags & IDENTIFY_UTF8)
c->tty.flags |= TTY_UTF8;
+ if (data.flags & IDENTIFY_256COLOURS)
+ c->tty.term_flags |= TERM_256COLOURS;
+ if (data.flags & IDENTIFY_HASDEFAULTS)
+ c->tty.term_flags |= TERM_HASDEFAULTS;
xfree(term);
c->flags |= CLIENT_TERMINAL;
diff --git a/server.c b/server.c
index d5bd5bab..4553f6af 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $Id: server.c,v 1.80 2008-09-10 19:15:04 nicm Exp $ */
+/* $Id: server.c,v 1.81 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -186,14 +186,14 @@ server_main(const char *srv_path, int srv_fd)
server_fill_clients(&pfd);
/* Do the poll. */
- log_debug("polling %d fds", nfds);
+ /* log_debug("polling %d fds", nfds); */
if ((nfds = poll(pfds, nfds, 100)) == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
fatal("poll failed");
}
pfd = pfds;
- log_debug("poll returned %d", nfds);
+ /* log_debug("poll returned %d", nfds); */
/* Handle server socket. */
#ifndef BROKEN_POLL
@@ -271,7 +271,7 @@ server_fill_windows(struct pollfd **pfd)
(*pfd)->events = POLLIN;
if (BUFFER_USED(w->out) > 0)
(*pfd)->events |= POLLOUT;
- log_debug("adding window %d (%d)", (*pfd)->fd, w->fd);
+ /* log_debug("adding window %d (%d)", (*pfd)->fd, w->fd); */
}
(*pfd)++;
}
@@ -286,7 +286,7 @@ server_handle_windows(struct pollfd **pfd)
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) != NULL && w->fd != -1) {
- log_debug("testing window %d (%d)", (*pfd)->fd, w->fd);
+ /* log_debug("testing window %d (%d)", (*pfd)->fd, w->fd); */
if (buffer_poll(*pfd, w->in, w->out) != 0)
server_lost_window(w);
else
@@ -303,6 +303,7 @@ server_check_redraw(struct client *c)
struct session *s;
struct screen_redraw_ctx ctx;
struct screen screen;
+ struct grid_cell gc;
u_int xx, yy, sx, sy;
char title[BUFSIZ];
int flags;
@@ -344,8 +345,9 @@ server_check_redraw(struct client *c)
if (sx < xx)
screen_redraw_columns(&ctx, sx, xx - sx);
if (sy < yy) {
- screen_fill_area(
- &screen, 0, sy, xx, 1, '-', 0, 8, 8);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ gc.data = '-';
+ grid_view_fill(screen.grid, &gc, 0, sy, xx, 1);
screen_redraw_lines(&ctx, sy, yy - sy);
}
screen_redraw_stop(&ctx);
@@ -423,7 +425,7 @@ server_fill_clients(struct pollfd **pfd)
(*pfd)->events = POLLIN;
if (BUFFER_USED(c->out) > 0)
(*pfd)->events |= POLLOUT;
- log_debug("adding client %d (%d)", (*pfd)->fd, c->fd);
+ /* log_debug("adding client %d (%d)", (*pfd)->fd, c->fd); */
}
(*pfd)++;
@@ -434,7 +436,7 @@ server_fill_clients(struct pollfd **pfd)
(*pfd)->events = POLLIN;
if (BUFFER_USED(c->tty.out) > 0)
(*pfd)->events |= POLLOUT;
- log_debug("adding tty %d (%d)", (*pfd)->fd, c->tty.fd);
+ /* log_debug("adding tty %d (%d)", (*pfd)->fd, c->tty.fd); */
}
(*pfd)++;
}
@@ -451,7 +453,7 @@ server_handle_clients(struct pollfd **pfd)
c = ARRAY_ITEM(&clients, i);
if (c != NULL) {
- log_debug("testing client %d (%d)", (*pfd)->fd, c->fd);
+ /* log_debug("testing client %d (%d)", (*pfd)->fd, c->fd); */
if (buffer_poll(*pfd, c->in, c->out) != 0) {
server_lost_client(c);
(*pfd) += 2;
@@ -462,7 +464,7 @@ server_handle_clients(struct pollfd **pfd)
(*pfd)++;
if (c != NULL && c->tty.fd != -1 && c->session != NULL) {
- log_debug("testing tty %d (%d)", (*pfd)->fd, c->tty.fd);
+ /* log_debug("testing tty %d (%d)", (*pfd)->fd, c->tty.fd); */
if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0)
server_lost_client(c);
else
@@ -594,12 +596,12 @@ server_handle_window(struct window *w)
action = options_get_number(&s->options, "bell-action");
switch (action) {
case BELL_ANY:
- tty_write_session(s, TTY_CHARACTER, '\007');
+ tty_write_session(s, TTY_BELL);
break;
case BELL_CURRENT:
if (s->curw->window != w)
break;
- tty_write_session(s, TTY_CHARACTER, '\007');
+ tty_write_session(s, TTY_BELL);
break;
}
update = 1;
diff --git a/status.c b/status.c
index 6f2a534d..a420b8ae 100644
--- a/status.c
+++ b/status.c
@@ -1,4 +1,4 @@
-/* $Id: status.c,v 1.45 2008-09-08 22:03:54 nicm Exp $ */
+/* $Id: status.c,v 1.46 2008-09-25 20:08:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -25,7 +25,7 @@
#include "tmux.h"
size_t status_width(struct winlink *);
-char *status_print(struct session *, struct winlink *, u_short *);
+char *status_print(struct session *, struct winlink *, struct grid_cell *);
/* Draw status for client on the last lines of given context. */
void
@@ -38,8 +38,7 @@ status_redraw(struct client *c)
char lbuf[BUFSIZ], rbuf[BUFSIZ];
size_t llen, rlen, offset, xx, yy;
size_t size, start, width;
- u_short attr;
- u_char fg, bg;
+ struct grid_cell gc;
struct tm *tm;
time_t t;
int larrow, rarrow;
@@ -50,8 +49,8 @@ status_redraw(struct client *c)
if (gettimeofday(&c->status_timer, NULL) != 0)
fatal("gettimeofday");
- fg = options_get_number(&s->options, "status-fg");
- bg = options_get_number(&s->options, "status-bg");
+ gc.fg = options_get_number(&s->options, "status-fg");
+ gc.bg = options_get_number(&s->options, "status-bg");
yy = c->sy - 1;
if (yy == 0)
@@ -138,24 +137,22 @@ draw:
/* Begin drawing and move to the starting position. */
screen_redraw_start_client(&ctx, c);
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
if (llen != 0) {
- screen_redraw_move_cursor(&ctx, 0, yy);
- screen_redraw_write_string(&ctx, "%s ", lbuf);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
+ screen_redraw_puts(&ctx, &gc, "%s ", lbuf);
if (larrow)
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
} else {
if (larrow)
- screen_redraw_move_cursor(&ctx, 1, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 1, yy);
else
- screen_redraw_move_cursor(&ctx, 0, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
}
/* Draw each character in succession. */
offset = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
- text = status_print(s, wl, &attr);
- screen_redraw_set_attributes(&ctx, attr, fg, bg);
+ text = status_print(s, wl, &gc);
if (larrow == 1 && offset < start) {
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
@@ -166,7 +163,7 @@ draw:
for (ptr = text; *ptr != '\0'; ptr++) {
if (offset >= start && offset < start + width)
- ctx.write(ctx.data, TTY_CHARACTER, *ptr);
+ screen_redraw_putc(&ctx, &gc, *ptr);
offset++;
}
@@ -177,10 +174,10 @@ draw:
rarrow = -1;
}
+ gc.attr &= ~GRID_ATTR_REVERSE;
if (offset < start + width) {
if (offset >= start) {
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
}
offset++;
}
@@ -189,52 +186,50 @@ draw:
}
/* Fill the remaining space if any. */
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
while (offset++ < xx)
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
/* Draw the last item. */
if (rlen != 0) {
- screen_redraw_move_cursor(&ctx, c->sx - rlen - 1, yy);
- screen_redraw_write_string(&ctx, " %s", rbuf);
+ ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 1, yy);
+ screen_redraw_puts(&ctx, &gc, " %s", rbuf);
}
/* Draw the arrows. */
if (larrow != 0) {
- if (larrow == -1) {
- screen_redraw_set_attributes(
- &ctx, ATTR_REVERSE, fg, bg);
- } else
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
+ if (larrow == -1)
+ gc.attr |= GRID_ATTR_REVERSE;
+ else
+ gc.attr &= ~GRID_ATTR_REVERSE;
if (llen != 0)
- screen_redraw_move_cursor(&ctx, llen + 1, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, llen + 1, yy);
else
- screen_redraw_move_cursor(&ctx, 0, yy);
- ctx.write(ctx.data, TTY_CHARACTER, '<');
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
+ screen_redraw_putc(&ctx, &gc, '<');
+ gc.attr &= ~GRID_ATTR_REVERSE;
}
if (rarrow != 0) {
- if (rarrow == -1) {
- screen_redraw_set_attributes(
- &ctx, ATTR_REVERSE, fg, bg);
- } else
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
+ if (rarrow == -1)
+ gc.attr |= GRID_ATTR_REVERSE;
+ else
+ gc.attr &= ~GRID_ATTR_REVERSE;
if (rlen != 0)
- screen_redraw_move_cursor(&ctx, c->sx - rlen - 2, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 2, yy);
else
- screen_redraw_move_cursor(&ctx, c->sx - 1, yy);
- ctx.write(ctx.data, TTY_CHARACTER, '>');
+ ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - 1, yy);
+ screen_redraw_putc(&ctx, &gc, '>');
+ gc.attr &= ~GRID_ATTR_REVERSE;
}
-
+
screen_redraw_stop(&ctx);
return;
blank:
/* Just draw the whole line as blank. */
screen_redraw_start_client(&ctx, c);
- screen_redraw_set_attributes(&ctx, 0, fg, bg);
- screen_redraw_move_cursor(&ctx, 0, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
for (offset = 0; offset < c->sx; offset++)
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
screen_redraw_stop(&ctx);
return;
@@ -247,10 +242,9 @@ off:
screen_redraw_start_client(&ctx, c);
/* If the screen is too small, use blank. */
if (screen_size_y(c->session->curw->window->screen) < c->sy) {
- screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
- screen_redraw_set_attributes(&ctx, 0, 8, 8);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, c->sy - 1);
for (offset = 0; offset < c->sx; offset++)
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
} else
screen_redraw_lines(&ctx, c->sy - 1, 1);
screen_redraw_stop(&ctx);
@@ -276,7 +270,7 @@ status_width(struct winlink *wl)
}
char *
-status_print(struct session *s, struct winlink *wl, u_short *attr)
+status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
{
char *text, flag;
@@ -286,14 +280,14 @@ status_print(struct session *s, struct winlink *wl, u_short *attr)
if (wl == s->curw)
flag = '*';
- *attr = 0;
+ gc->attr &= ~GRID_ATTR_REVERSE;
if (session_alert_has(s, wl, WINDOW_ACTIVITY)) {
flag = '#';
- *attr = ATTR_REVERSE;
+ gc->attr |= GRID_ATTR_REVERSE;
}
if (session_alert_has(s, wl, WINDOW_BELL)) {
flag = '!';
- *attr = ATTR_REVERSE;
+ gc->attr |= GRID_ATTR_REVERSE;
}
xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag);
@@ -306,6 +300,7 @@ status_message_redraw(struct client *c)
{
struct screen_redraw_ctx ctx;
size_t xx, yy;
+ struct grid_cell gc;
if (c->sx == 0 || c->sy == 0)
return;
@@ -315,16 +310,19 @@ status_message_redraw(struct client *c)
xx = c->sx;
yy = c->sy - 1;
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ gc.attr |= GRID_ATTR_REVERSE;
+
screen_redraw_start_client(&ctx, c);
- screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
- screen_redraw_move_cursor(&ctx, 0, yy);
- screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->message_string);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
+ screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->message_string);
for (; xx < c->sx; xx++)
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
+
screen_redraw_stop(&ctx);
- tty_write_client(c, TTY_CURSOROFF);
+ tty_write_client(c, TTY_CURSORMODE, 0);
}
/* Draw client prompt on status line of present else on last line. */
@@ -334,6 +332,7 @@ status_prompt_redraw(struct client *c)
struct screen_redraw_ctx ctx;
size_t i, xx, yy, left, size, offset;
char ch;
+ struct grid_cell gc;
if (c->sx == 0 || c->sy == 0)
return;
@@ -344,11 +343,13 @@ status_prompt_redraw(struct client *c)
xx = c->sx;
yy = c->sy - 1;
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ gc.attr |= GRID_ATTR_REVERSE;
+
screen_redraw_start_client(&ctx, c);
- screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
- screen_redraw_move_cursor(&ctx, 0, yy);
- screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->prompt_string);
+ ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
+ screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->prompt_string);
left = c->sx - xx;
if (left != 0) {
@@ -360,29 +361,29 @@ status_prompt_redraw(struct client *c)
left--;
size = left;
}
- screen_redraw_write_string(
- &ctx, "%.*s", (int) left, c->prompt_buffer + offset);
+ screen_redraw_puts(
+ &ctx, &gc, "%.*s", (int) left, c->prompt_buffer + offset);
for (i = xx + size; i < c->sx; i++) {
- ctx.write(ctx.data, TTY_CHARACTER, ' ');
+ screen_redraw_putc(&ctx, &gc, ' ');
ctx.s->cx++;
}
}
/* Draw a fake cursor. */
- screen_redraw_set_attributes(&ctx, 0, 8, 8);
- screen_redraw_move_cursor(&ctx, xx + c->prompt_index - offset, yy);
+ ctx.write(ctx.data, TTY_CURSORMOVE, xx + c->prompt_index - offset, yy);
if (c->prompt_index == strlen(c->prompt_buffer))
ch = ' ';
else
ch = c->prompt_buffer[c->prompt_index];
if (ch == '\0')
ch = ' ';
- tty_write_client(c, TTY_CHARACTER, ch);
+ gc.attr &= ~GRID_ATTR_REVERSE;
+ screen_redraw_putc(&ctx, &gc, ch);
screen_redraw_stop(&ctx);
- tty_write_client(c, TTY_CURSOROFF);
+ tty_write_client(c, TTY_CURSORMODE, 0);
}
/* Handle keys in prompt. */
diff --git a/tmux.1 b/tmux.1
index a10468dd..799ace09 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1,4 +1,4 @@
-.\" $Id: tmux.1,v 1.48 2008-06-30 18:27:14 nicm Exp $
+.\" $Id: tmux.1,v 1.49 2008-09-25 20:08:56 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
@@ -668,6 +668,15 @@ maintain this maximum length.
Set the maximum number of lines held in window history.
This setting applies only to new windows - existing window histories are not
resized and retain the limit at the point they were created.
+.It Xo Ic mode-keys
+.Op Ic vi | Ic emacs
+.Xc
+Use
+.Xr vi 1 -
+or
+.Xr emacs 1 -
+style key bindings in scroll and copy modes.
+Key bindings default to emacs.
.It Ic prefix Ar key
Set the current prefix key.
.It Xo Ic remain-by-default
diff --git a/tmux.c b/tmux.c
index fb7e56f7..bf52e2ea 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.75 2008-09-09 22:16:37 nicm Exp $ */
+/* $Id: tmux.c,v 1.76 2008-09-25 20:08:56 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -62,7 +62,7 @@ __dead void
usage(void)
{
fprintf(stderr,
- "usage: %s [-qVv] [-f file] [-S socket-path] [command [flags]]\n",
+ "usage: %s [-2dquVv] [-f file] [-S socket-path] [command [flags]]\n",
__progname);
exit(1);
}
@@ -179,8 +179,11 @@ main(int argc, char **argv)
flags = 0;
path = NULL;
- while ((opt = getopt(argc, argv, "f:qS:uVv")) != EOF) {
+ while ((opt = getopt(argc, argv, "2df:qS:uVv")) != EOF) {
switch (opt) {
+ case '2':
+ flags |= IDENTIFY_256COLOURS;
+ break;
case 'f':
cfg_file = xstrdup(optarg);
break;
@@ -193,6 +196,9 @@ main(int argc, char **argv)
case 'u':
flags |= IDENTIFY_UTF8;
break;
+ case 'd':
+ flags |= IDENTIFY_HASDEFAULTS;
+ break;
case 'v':
debug_level++;
break;
diff --git a/tmux.h b/tmux.h
index ccf87657..d74b9e00 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.188 2008-09-10 19:15:04 nicm Exp $ */
+/* $Id: tmux.h,v 1.189 2008-09-25 20:08:56 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
-#define PROTOCOL_VERSION -2
+#define PROTOCOL_VERSION -3
/* Shut up gcc warnings about empty if bodies. */
#define RB_AUGMENT(x) do {} while (0)
@@ -321,28 +321,32 @@ struct buffer {
#define KEYC_KP4_2 (KEYC_OFFSET + 0x10f)
/* Output codes. */
-#define TTY_CHARACTER 0
-#define TTY_CURSORUP 1
-#define TTY_CURSORDOWN 2
-#define TTY_CURSORRIGHT 3
-#define TTY_CURSORLEFT 4
-#define TTY_INSERTCHARACTER 5
-#define TTY_DELETECHARACTER 6
-#define TTY_INSERTLINE 7
-#define TTY_DELETELINE 8
-#define TTY_CLEARLINE 9
-#define TTY_CLEARENDOFLINE 10
-#define TTY_CLEARSTARTOFLINE 11
-#define TTY_CURSORMOVE 12
-#define TTY_ATTRIBUTES 13
-#define TTY_CURSOROFF 14
-#define TTY_CURSORON 15
-#define TTY_REVERSEINDEX 16
-#define TTY_SCROLLREGION 17
-#define TTY_INSERTON 18
-#define TTY_INSERTOFF 19
-#define TTY_MOUSEON 20
-#define TTY_MOUSEOFF 21 /* XXX merge all on/off into 1 arg? */
+#define TTY_CURSORUP 0
+#define TTY_CURSORDOWN 1
+#define TTY_CURSORRIGHT 2
+#define TTY_CURSORLEFT 3
+#define TTY_INSERTCHARACTER 4
+#define TTY_DELETECHARACTER 5
+#define TTY_INSERTLINE 6
+#define TTY_DELETELINE 7
+#define TTY_CLEARLINE 8
+#define TTY_CLEARENDOFLINE 9
+#define TTY_CLEARSTARTOFLINE 10
+#define TTY_CURSORMOVE 11
+#define TTY_CURSORMODE 12
+#define TTY_REVERSEINDEX 13
+#define TTY_SCROLLREGION 14
+#define TTY_INSERTMODE 15
+#define TTY_MOUSEMODE 16
+#define TTY_LINEFEED 17
+#define TTY_CARRIAGERETURN 18
+#define TTY_BELL 19
+#define TTY_KCURSORMODE 20
+#define TTY_KKEYPADMODE 21
+#define TTY_CLEARENDOFSCREEN 22
+#define TTY_CLEARSTARTOFSCREEN 23
+#define TTY_CLEARSCREEN 24
+#define TTY_CELL 25
/* Message codes. */
enum hdrtype {
@@ -376,6 +380,8 @@ struct msg_identify_data {
int version;
#define IDENTIFY_UTF8 0x1
+#define IDENTIFY_256COLOURS 0x2
+#define IDENTIFY_HASDEFAULTS 0x4
int flags;
u_int sx;
@@ -389,45 +395,52 @@ struct msg_resize_data {
u_int sy;
};
-/* UTF8 data. */
-struct utf8_data {
- u_char data[4];
-};
-
-struct utf8_table {
- u_int limit;
- ARRAY_DECL(, struct utf8_data) array;
-};
-#define UTF8_LIMIT ((1<<11) - 1)
-
-/* Attributes. */
-#define ATTR_BRIGHT 0x1
-#define ATTR_DIM 0x2
-#define ATTR_UNDERSCORE 0x4
-#define ATTR_BLINK 0x8
-#define ATTR_REVERSE 0x10
-#define ATTR_HIDDEN 0x20
-#define ATTR_ITALICS 0x40
-#define ATTR_CHARSET 0x80 /* alternative character set */
-
-#define ATTR_FG256 0x100
-#define ATTR_BG256 0x200
-
-#define ATTR_UTF8 0x400
-#define ATTR_PAD 0x800
-
-#define ATTR_UTF8b8 0x8000
-#define ATTR_UTF8b9 0x4000
-#define ATTR_UTF8b10 0x2000
-#define ATTR_UTF8b11 0x1000
-
/* Modes. */
#define MODE_CURSOR 0x1
#define MODE_INSERT 0x2
#define MODE_KCURSOR 0x4
#define MODE_KKEYPAD 0x8
-#define MODE_SAVED 0x10
-#define MODE_MOUSE 0x20
+#define MODE_MOUSE 0x10
+
+/* Grid output. */
+#define GRID_DEBUG(gd, fmt, ...) log_debug3("%s: (sx=%u, sy=%u, hsize=%u) " \
+ fmt, __func__, (gd)->sx, (gd)->sy, (gd)->hsize, ## __VA_ARGS__)
+
+/* Grid attributes. */
+#define GRID_ATTR_BRIGHT 0x1
+#define GRID_ATTR_DIM 0x2
+#define GRID_ATTR_UNDERSCORE 0x4
+#define GRID_ATTR_BLINK 0x8
+#define GRID_ATTR_REVERSE 0x10
+#define GRID_ATTR_HIDDEN 0x20
+#define GRID_ATTR_ITALICS 0x40
+#define GRID_ATTR_CHARSET 0x80 /* alternative character set */
+
+/* Grid flags. */
+#define GRID_FLAG_FG256 0x1
+#define GRID_FLAG_BG256 0x2
+#define GRID_FLAG_PADDING 0x4
+
+/* Grid cell. */
+struct grid_cell {
+ u_short data;
+ u_char attr;
+ u_char flags;
+ u_char fg;
+ u_char bg;
+} __packed;
+
+/* Grid data. */
+struct grid_data {
+ u_int sx;
+ u_int sy;
+
+ u_int hsize;
+ u_int hlimit;
+
+ u_int *size;
+ struct grid_cell **data;
+};
/* Screen selection. */
struct screen_sel {
@@ -444,34 +457,13 @@ struct screen_sel {
struct screen {
char *title;
- u_char **grid_data;
- u_short **grid_attr;
- u_char **grid_fg;
- u_char **grid_bg;
- u_int *grid_size;
-
- u_int dx; /* display x size */
- u_int dy; /* display 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 */
+ struct grid_data *grid; /* grid data */
u_int cx; /* cursor x */
u_int cy; /* cursor y */
- u_short attr;
- u_char fg;
- u_char bg;
-
- struct utf8_table utf8_table;
- u_int saved_cx;
- u_int saved_cy;
- u_short saved_attr;
- u_char saved_fg;
- u_char saved_bg;
+ u_int rupper; /* scroll region top */
+ u_int rlower; /* scroll region bottom */
int mode;
@@ -497,51 +489,11 @@ struct screen_write_ctx {
struct screen *s;
};
-/* Screen display access macros. */
-#define screen_x(s, x) (x)
-#define screen_y(s, y) ((s)->hsize + 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)
-
-/* These are inclusive... */
-#define screen_left_x(s, x) ((x) + 1)
-#define screen_right_x(s, x) \
- ((x) < screen_size_x(s) ? screen_size_x(s) - (x) : 0)
-
-#define screen_above_y(s, y) ((y) + 1)
-#define screen_below_y(s, y) \
- ((y) < screen_size_y(s) ? screen_size_y(s) - (y) : 0)
-
-#define SCREEN_DEBUG(s) do { \
- log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u", __func__, \
- s->cx, s->cy, screen_size_x(s), screen_size_y(s)); \
-} while (0)
-#define SCREEN_DEBUG1(s, n) do { \
- log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u", __func__, \
- s->cx, s->cy, screen_size_x(s), screen_size_y(s), n); \
-} while (0)
-#define SCREEN_DEBUG2(s, n, m) do { \
- log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u", __func__, \
- s->cx, s->cy, screen_size_x(s), screen_size_y(s), n, m); \
-} while (0)
-#define SCREEN_DEBUG3(s, n, m, o) do { \
- log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u o=%u", \
- __func__, s->cx, s->cy, screen_size_x(s), screen_size_y(s), \
- n, m, o); \
-} while (0)
-#define SCREEN_DEBUG4(s, n, m, o, p) do { \
- log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u o=%u p=%u", \
- __func__, s->cx, s->cy, screen_size_x(s), screen_size_y(s), \
- n, m, o, p); \
-} while (0)
+/* Screen size. */
+#define screen_size_x(s) ((s)->grid->sx)
+#define screen_size_y(s) ((s)->grid->sy)
+#define screen_hsize(s) ((s)->grid->hsize)
+#define screen_hlimit(s) ((s)->grid->hlimit)
/* Input parser sequence argument. */
struct input_arg {
@@ -558,6 +510,12 @@ struct input_ctx {
size_t len;
size_t off;
+ struct grid_cell cell; /* current cell data */
+
+ struct grid_cell saved_cell;
+ u_int saved_cx;
+ u_int saved_cy;
+
#define MAXSTRINGLEN 1024
u_char *string_buf;
size_t string_len;
@@ -566,7 +524,7 @@ struct input_ctx {
#define STRING_NAME 1
#define STRING_IGNORE 2
- struct utf8_data utf8_buf;
+ u_char utf8_buf[4];
u_int utf8_len;
u_int utf8_off;
@@ -725,9 +683,7 @@ struct tty {
struct termios tio;
- u_short attr;
- u_char fg;
- u_char bg;
+ struct grid_cell cell;
u_char acs[UCHAR_MAX + 1];
@@ -737,6 +693,8 @@ struct tty {
#define TTY_UTF8 0x8
int flags;
+ int term_flags;
+
struct timeval key_timer;
size_t ksize; /* maximum key size */
@@ -1175,65 +1133,85 @@ void input_key(struct window *, int);
const char *colour_tostring(u_char);
u_char colour_fromstring(const char *);
-/* screen-display.c */
-void screen_display_get_cell(struct screen *,
- u_int, u_int, u_char *, u_short *, u_char *, u_char *);
-void screen_display_set_cell(
- struct screen *, u_int, u_int, u_char, u_short, u_char, u_char);
-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_area(struct screen *,
- u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char);
-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);
-void screen_display_copy_area(struct screen *, struct screen *,
- u_int, u_int, u_int, u_int, u_int, u_int);
+/* grid.c */
+extern const struct grid_cell grid_default_cell;
+struct grid_data *grid_create(u_int, u_int, u_int);
+void grid_destroy(struct grid_data *);
+void grid_reduce_line(struct grid_data *, u_int, u_int);
+void grid_expand_line(struct grid_data *, u_int, u_int);
+void grid_scroll_line(struct grid_data *);
+const struct grid_cell *grid_peek_cell(struct grid_data *, u_int, u_int);
+struct grid_cell *grid_get_cell(struct grid_data *, u_int, u_int);
+void grid_set_cell(
+ struct grid_data *, u_int, u_int, const struct grid_cell *);
+void grid_clear(struct grid_data *, u_int, u_int, u_int, u_int);
+void grid_fill(struct grid_data *,
+ const struct grid_cell *, u_int, u_int, u_int, u_int);
+void grid_fill_lines(
+ struct grid_data *, const struct grid_cell *, u_int, u_int);
+void grid_clear_lines(struct grid_data *, u_int, u_int);
+void grid_move_lines(struct grid_data *, u_int, u_int, u_int);
+void grid_clear_cells(struct grid_data *, u_int, u_int, u_int);
+void grid_move_cells(struct grid_data *, u_int, u_int, u_int, u_int);
+
+/* grid-view.c */
+const struct grid_cell *grid_view_peek_cell(struct grid_data *, u_int, u_int);
+struct grid_cell *grid_view_get_cell(struct grid_data *, u_int, u_int);
+void grid_view_set_cell(
+ struct grid_data *, u_int, u_int, const struct grid_cell *);
+void grid_view_clear(struct grid_data *, u_int, u_int, u_int, u_int);
+void grid_view_fill(struct grid_data *,
+ const struct grid_cell *, u_int, u_int, u_int, u_int);
+void grid_view_scroll_region_up(struct grid_data *, u_int, u_int);
+void grid_view_scroll_region_down(struct grid_data *, u_int, u_int);
+void grid_view_insert_lines(struct grid_data *, u_int, u_int);
+void grid_view_insert_lines_region(
+ struct grid_data *, u_int, u_int, u_int, u_int);
+void grid_view_delete_lines(struct grid_data *, u_int, u_int);
+void grid_view_delete_lines_region(
+ struct grid_data *, u_int, u_int, u_int, u_int);
+void grid_view_insert_cells(struct grid_data *, u_int, u_int, u_int);
+void grid_view_delete_cells(struct grid_data *, u_int, u_int, u_int);
/* screen-write.c */
void screen_write_start_window(struct screen_write_ctx *, struct window *);
void screen_write_start_client(struct screen_write_ctx *, struct client *);
void screen_write_start_session(
- struct screen_write_ctx *, struct session *);
+ struct screen_write_ctx *, struct session *);
void screen_write_start(struct screen_write_ctx *,
- struct screen *, void (*)(void *, int, ...), void *);
+ struct screen *, void (*)(void *, int, ...), void *);
void screen_write_stop(struct screen_write_ctx *);
-void screen_write_set_title(struct screen_write_ctx *, char *);
-void screen_write_put_character(struct screen_write_ctx *, u_char);
-void screen_write_put_utf8(struct screen_write_ctx *, struct utf8_data *);
-size_t printflike2 screen_write_put_string_rjust(
- struct screen_write_ctx *, const char *, ...);
-void printflike2 screen_write_put_string(
- struct screen_write_ctx *, const char *, ...);
-void screen_write_set_attributes(
- struct screen_write_ctx *, u_short, u_char, u_char);
-void screen_write_set_region(struct screen_write_ctx *, u_int, u_int);
-void screen_write_cursor_up_scroll(struct screen_write_ctx *);
-void screen_write_cursor_down_scroll(struct screen_write_ctx *);
-void screen_write_cursor_up(struct screen_write_ctx *, u_int);
-void screen_write_cursor_down(struct screen_write_ctx *, u_int);
-void screen_write_cursor_left(struct screen_write_ctx *, u_int);
-void screen_write_cursor_right(struct screen_write_ctx *, u_int);
-void screen_write_delete_lines(struct screen_write_ctx *, u_int);
-void screen_write_delete_characters(struct screen_write_ctx *, u_int);
-void screen_write_insert_lines(struct screen_write_ctx *, u_int);
-void screen_write_insert_characters(struct screen_write_ctx *, u_int);
-void screen_write_move_cursor(struct screen_write_ctx *, u_int, u_int);
-void screen_write_fill_end_of_screen(struct screen_write_ctx *);
-void screen_write_fill_screen(struct screen_write_ctx *);
-void screen_write_fill_end_of_line(struct screen_write_ctx *);
-void screen_write_fill_start_of_line(struct screen_write_ctx *);
-void screen_write_fill_line(struct screen_write_ctx *);
-void screen_write_set_mode(struct screen_write_ctx *, int);
-void screen_write_clear_mode(struct screen_write_ctx *, int);
-void screen_write_copy_area(struct screen_write_ctx *,
- struct screen *, u_int, u_int, u_int, u_int);
+void printflike3 screen_write_puts(
+ struct screen_write_ctx *, struct grid_cell *, const char *, ...);
+void screen_write_putc(
+ struct screen_write_ctx *, struct grid_cell *, u_char);
+void screen_write_copy(struct screen_write_ctx *,
+ struct screen *, u_int, u_int, u_int, u_int);
+void screen_write_cursorup(struct screen_write_ctx *, u_int);
+void screen_write_cursordown(struct screen_write_ctx *, u_int);
+void screen_write_cursorright(struct screen_write_ctx *, u_int);
+void screen_write_cursorleft(struct screen_write_ctx *, u_int);
+void screen_write_insertcharacter(struct screen_write_ctx *, u_int);
+void screen_write_deletecharacter(struct screen_write_ctx *, u_int);
+void screen_write_insertline(struct screen_write_ctx *, u_int);
+void screen_write_deleteline(struct screen_write_ctx *, u_int);
+void screen_write_clearline(struct screen_write_ctx *);
+void screen_write_clearendofline(struct screen_write_ctx *);
+void screen_write_clearstartofline(struct screen_write_ctx *);
+void screen_write_cursormove(struct screen_write_ctx *, u_int, u_int);
+void screen_write_cursormode(struct screen_write_ctx *, int);
+void screen_write_reverseindex(struct screen_write_ctx *);
+void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
+void screen_write_insertmode(struct screen_write_ctx *, int);
+void screen_write_mousemode(struct screen_write_ctx *, int);
+void screen_write_linefeed(struct screen_write_ctx *);
+void screen_write_carriagereturn(struct screen_write_ctx *);
+void screen_write_kcursormode(struct screen_write_ctx *, int);
+void screen_write_kkeypadmode(struct screen_write_ctx *, int);
+void screen_write_clearendofscreen(struct screen_write_ctx *);
+void screen_write_clearstartofscreen(struct screen_write_ctx *);
+void screen_write_clearscreen(struct screen_write_ctx *);
+void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *);
/* screen-redraw.c */
void screen_redraw_start_window(struct screen_redraw_ctx *, struct window *);
@@ -1243,14 +1221,11 @@ void screen_redraw_start_session(
void screen_redraw_start(struct screen_redraw_ctx *,
struct screen *, void (*)(void *, int, ...), void *);
void screen_redraw_stop(struct screen_redraw_ctx *);
-void screen_redraw_move_cursor(struct screen_redraw_ctx *, u_int, u_int);
-void screen_redraw_set_attributes(
- struct screen_redraw_ctx *, u_short, u_char, u_char);
-void printflike2 screen_redraw_write_string(
- struct screen_redraw_ctx *, const char *, ...);
+void printflike3 screen_redraw_puts(
+ struct screen_redraw_ctx *, struct grid_cell *, const char *, ...);
+void screen_redraw_putc(
+ struct screen_redraw_ctx *, struct grid_cell *, u_char);
void screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int);
-void screen_redraw_area(
- struct screen_redraw_ctx *, u_int, u_int, u_int, u_int);
void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int);
void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int);
@@ -1258,21 +1233,13 @@ void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int);
void screen_init(struct screen *, u_int, u_int, u_int);
void screen_reinit(struct screen *);
void screen_free(struct screen *);
+void screen_set_title(struct screen *, const char *);
void screen_resize(struct screen *, u_int, u_int);
-void screen_expand_line(struct screen *, u_int, u_int);
-void screen_reduce_line(struct screen *, u_int, u_int);
-void screen_get_cell(struct screen *,
- u_int, u_int, u_char *, u_short *, u_char *, u_char *);
-void screen_set_cell(
- struct screen *, u_int, u_int, u_char, u_short, 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_area(struct screen *,
- u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char);
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int);
void screen_clear_selection(struct screen *);
int screen_check_selection(struct screen *, u_int, u_int);
+void screen_display_copy_area(struct screen *, struct screen *,
+ u_int, u_int, u_int, u_int, u_int, u_int);
/* window.c */
extern struct windows windows;
@@ -1328,13 +1295,9 @@ int session_select(struct session *, int);
int session_last(struct session *);
/* utf8.c */
-void utf8_pack(int, u_char *, u_short *);
-int utf8_unpack(u_char, u_short);
-void utf8_init(struct utf8_table *, int);
-void utf8_free(struct utf8_table *);
-struct utf8_data *utf8_lookup(struct utf8_table *, int);
-int utf8_search(struct utf8_table *, struct utf8_data *);
-int utf8_add(struct utf8_table *, struct utf8_data *);
+u_int utf8_combine(const u_char [4]);
+void utf8_split(u_int, u_char [4]);
+int utf8_width(u_int);
/* buffer.c */
struct buffer *buffer_create(size_t);
diff --git a/tty.c b/tty.c
index 39c58087..74b75c20 100644
--- a/tty.c
+++ b/tty.c
@@ -1,4 +1,4 @@
-/* $Id: tty.c,v 1.42 2008-09-23 17:54:35 nicm Exp $ */
+/* $Id: tty.c,v 1.43 2008-09-25 20:08:56 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -39,10 +39,64 @@ void tty_raw(struct tty *, const char *);
void tty_puts(struct tty *, const char *);
void tty_putc(struct tty *, char);
-void tty_attributes(struct tty *, u_short, u_char, u_char);
-u_char tty_attributes_fg(struct tty *, u_char);
-u_char tty_attributes_bg(struct tty *, u_char);
-char tty_translate(char);
+void tty_reset(struct tty *);
+void tty_attributes(struct tty *, const struct grid_cell *);
+void tty_attributes_fg(struct tty *, const struct grid_cell *);
+void tty_attributes_bg(struct tty *, const struct grid_cell *);
+
+void tty_cmd_cursorup(struct tty *, struct screen *, va_list);
+void tty_cmd_cursordown(struct tty *, struct screen *, va_list);
+void tty_cmd_cursorright(struct tty *, struct screen *, va_list);
+void tty_cmd_cursorleft(struct tty *, struct screen *, va_list);
+void tty_cmd_insertcharacter(struct tty *, struct screen *, va_list);
+void tty_cmd_deletecharacter(struct tty *, struct screen *, va_list);
+void tty_cmd_insertline(struct tty *, struct screen *, va_list);
+void tty_cmd_deleteline(struct tty *, struct screen *, va_list);
+void tty_cmd_clearline(struct tty *, struct screen *, va_list);
+void tty_cmd_clearendofline(struct tty *, struct screen *, va_list);
+void tty_cmd_clearstartofline(struct tty *, struct screen *, va_list);
+void tty_cmd_cursormove(struct tty *, struct screen *, va_list);
+void tty_cmd_cursormode(struct tty *, struct screen *, va_list);
+void tty_cmd_reverseindex(struct tty *, struct screen *, va_list);
+void tty_cmd_scrollregion(struct tty *, struct screen *, va_list);
+void tty_cmd_insertmode(struct tty *, struct screen *, va_list);
+void tty_cmd_mousemode(struct tty *, struct screen *, va_list);
+void tty_cmd_linefeed(struct tty *, struct screen *, va_list);
+void tty_cmd_carriagereturn(struct tty *, struct screen *, va_list);
+void tty_cmd_bell(struct tty *, struct screen *, va_list);
+void tty_cmd_clearendofscreen(struct tty *, struct screen *, va_list);
+void tty_cmd_clearstartofscreen(struct tty *, struct screen *, va_list);
+void tty_cmd_clearscreen(struct tty *, struct screen *, va_list);
+void tty_cmd_cell(struct tty *, struct screen *, va_list);
+
+void (*tty_cmds[])(struct tty *, struct screen *, va_list) = {
+ tty_cmd_cursorup,
+ tty_cmd_cursordown,
+ tty_cmd_cursorright,
+ tty_cmd_cursorleft,
+ tty_cmd_insertcharacter,
+ tty_cmd_deletecharacter,
+ tty_cmd_insertline,
+ tty_cmd_deleteline,
+ tty_cmd_clearline,
+ tty_cmd_clearendofline,
+ tty_cmd_clearstartofline,
+ tty_cmd_cursormove,
+ tty_cmd_cursormode,
+ tty_cmd_reverseindex,
+ tty_cmd_scrollregion,
+ tty_cmd_insertmode,
+ tty_cmd_mousemode,
+ tty_cmd_linefeed,
+ tty_cmd_carriagereturn,
+ tty_cmd_bell,
+ NULL,
+ NULL,
+ tty_cmd_clearendofscreen,
+ tty_cmd_clearstartofscreen,
+ tty_cmd_clearscreen,
+ tty_cmd_cell,
+};
TAILQ_HEAD(, tty_term) tty_terms = TAILQ_HEAD_INITIALIZER(tty_terms);
@@ -55,6 +109,7 @@ tty_init(struct tty *tty, char *path, char *term)
else
tty->termname = xstrdup(term);
tty->flags = 0;
+ tty->term_flags = 0;
}
int
@@ -74,9 +129,9 @@ tty_open(struct tty *tty, char **cause)
if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl");
- if (debug_level > 3) {
+ if (debug_level > 3)
tty->log_fd = open("tmux.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
- } else
+ else
tty->log_fd = -1;
if ((tty->term = tty_find_term(tty->termname, tty->fd, cause)) == NULL)
@@ -86,10 +141,7 @@ tty_open(struct tty *tty, char **cause)
tty->out = buffer_create(BUFSIZ);
tty->flags &= TTY_UTF8;
-
- tty->attr = 0;
- tty->fg = 8;
- tty->bg = 8;
+ memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
if (tcgetattr(tty->fd, &tty->tio) != 0)
fatal("tcgetattr failed");
@@ -163,15 +215,17 @@ tty_close(struct tty *tty)
fatal("tcsetattr failed");
tty_raw(tty, tparm(change_scroll_region, 0, ws.ws_row - 1));
+ if (exit_alt_charset_mode != NULL)
+ tty_puts(tty, exit_alt_charset_mode);
+ if (exit_attribute_mode != NULL)
+ tty_raw(tty, exit_attribute_mode);
+ tty_raw(tty, clear_screen);
if (keypad_local != NULL)
tty_raw(tty, keypad_local);
if (exit_ca_mode != NULL)
tty_raw(tty, exit_ca_mode);
- tty_raw(tty, clear_screen);
if (cursor_normal != NULL)
tty_raw(tty, cursor_normal);
- if (exit_attribute_mode != NULL)
- tty_raw(tty, exit_attribute_mode);
}
tty_free_term(tty->term);
@@ -405,7 +459,7 @@ tty_puts(struct tty *tty, const char *s)
void
tty_putc(struct tty *tty, char ch)
{
- if (tty->attr & ATTR_CHARSET)
+ if (tty->cell.attr & GRID_ATTR_CHARSET)
ch = tty_get_acs(tty, ch);
buffer_write8(tty->out, ch);
@@ -429,10 +483,6 @@ tty_set_title(struct tty *tty, const char *title)
void
tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
{
- struct utf8_data *udat;
- char ch;
- u_int i, ua, ub, uc;
-
if (tty->flags & TTY_FREEZE)
return;
@@ -440,273 +490,493 @@ tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
return;
set_curterm(tty->term->term);
- switch (cmd) {
- case TTY_CHARACTER:
- ch = va_arg(ap, int);
-
- if (tty->attr & ATTR_PAD)
- break;
+ if (tty_cmds[cmd] != NULL)
+ tty_cmds[cmd](tty, s, ap);
+}
- if ((tty->attr & ATTR_UTF8) && (tty->flags & TTY_UTF8)) {
- udat = utf8_lookup(
- &s->utf8_table, utf8_unpack(ch, tty->attr));
- if (udat == NULL)
- ch = '_';
- else {
- if (udat->data[0] == 0xff)
- break;
- tty_putc(tty, udat->data[0]);
- if (udat->data[1] == 0xff)
- break;
- tty_putc(tty, udat->data[1]);
- if (udat->data[2] == 0xff)
- break;
- tty_putc(tty, udat->data[2]);
- if (udat->data[3] == 0xff)
- break;
- tty_putc(tty, udat->data[3]);
- break;
- }
- } else if (tty->attr & ATTR_UTF8)
- ch = '_';
-
- switch (ch) {
- case '\n': /* LF */
- tty_putc(tty, '\n');
- break;
- case '\r': /* CR */
- tty_puts(tty, carriage_return);
- break;
- case '\007': /* BEL */
- if (bell != NULL)
- tty_puts(tty, bell);
- break;
- case '\010': /* BS */
+void
+tty_cmd_cursorup(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ if (parm_up_cursor != NULL)
+ tty_puts(tty, tparm(parm_up_cursor, ua));
+ else {
+ while (ua-- > 0)
+ tty_puts(tty, cursor_up);
+ }
+}
+
+void
+tty_cmd_cursordown(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ if (parm_down_cursor != NULL)
+ tty_puts(tty, tparm(parm_down_cursor, ua));
+ else {
+ while (ua-- > 0)
+ tty_puts(tty, cursor_down);
+ }
+}
+
+void
+tty_cmd_cursorright(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ if (parm_right_cursor != NULL)
+ tty_puts(tty, tparm(parm_right_cursor, ua));
+ else {
+ while (ua-- > 0)
+ tty_puts(tty, cursor_right);
+ }
+}
+
+void
+tty_cmd_cursorleft(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ if (parm_left_cursor != NULL)
+ tty_puts(tty, tparm(parm_left_cursor, ua));
+ else {
+ while (ua-- > 0)
tty_puts(tty, cursor_left);
- break;
- default:
- tty_putc(tty, ch);
- break;
- }
- break;
- case TTY_CURSORUP:
- ua = va_arg(ap, u_int);
- if (parm_up_cursor != NULL)
- tty_puts(tty, tparm(parm_up_cursor, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, cursor_up);
- }
- break;
- case TTY_CURSORDOWN:
- ua = va_arg(ap, u_int);
- if (parm_down_cursor != NULL)
- tty_puts(tty, tparm(parm_down_cursor, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, cursor_down);
- }
- break;
- case TTY_CURSORRIGHT:
- ua = va_arg(ap, u_int);
- if (parm_right_cursor != NULL)
- tty_puts(tty, tparm(parm_right_cursor, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, cursor_right);
- }
- break;
- case TTY_CURSORLEFT:
- ua = va_arg(ap, u_int);
- if (parm_left_cursor != NULL)
- tty_puts(tty, tparm(parm_left_cursor, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, cursor_left);
- }
- break;
- case TTY_CURSORMOVE:
- ua = va_arg(ap, u_int);
- ub = va_arg(ap, u_int);
- tty_puts(tty, tparm(cursor_address, ua, ub));
- break;
- case TTY_CLEARENDOFLINE:
- if (clr_eol != NULL)
+ }
+}
+
+void
+tty_cmd_insertcharacter(struct tty *tty, struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ tty_reset(tty);
+
+ if (parm_ich != NULL)
+ tty_puts(tty, tparm(parm_ich, ua));
+ else if (insert_character != NULL) {
+ while (ua-- > 0)
+ tty_puts(tty, insert_character);
+ } else if (enter_insert_mode != NULL) {
+ tty_puts(tty, enter_insert_mode);
+ while (ua-- > 0)
+ tty_putc(tty, ' ');
+ tty_puts(tty, exit_insert_mode);
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ }
+}
+
+void
+tty_cmd_deletecharacter(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ tty_reset(tty);
+
+ if (parm_dch != NULL)
+ tty_puts(tty, tparm(parm_dch, ua));
+ else if (delete_character != NULL) {
+ while (ua-- > 0)
+ tty_puts(tty, delete_character);
+ } else {
+ while (ua-- > 0)
+ tty_putc(tty, '\010');
+ }
+}
+
+void
+tty_cmd_insertline(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ tty_reset(tty);
+
+ if (parm_insert_line != NULL)
+ tty_puts(tty, tparm(parm_insert_line, ua));
+ else {
+ while (ua-- > 0)
+ tty_puts(tty, insert_line);
+ }
+}
+
+void
+tty_cmd_deleteline(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ ua = va_arg(ap, u_int);
+
+ tty_reset(tty);
+
+ if (parm_delete_line != NULL)
+ tty_puts(tty, tparm(parm_delete_line, ua));
+ else {
+ while (ua-- > 0)
+ tty_puts(tty, delete_line);
+ }
+}
+
+void
+tty_cmd_clearline(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i;
+
+ tty_reset(tty);
+
+ if (clr_eol != NULL) {
+ tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ tty_puts(tty, clr_eol);
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ } else {
+ tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ for (i = 0; i < screen_size_x(s); i++)
+ tty_putc(tty, ' ');
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ }
+}
+
+void
+tty_cmd_clearendofline(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i;
+
+ tty_reset(tty);
+
+ if (clr_eol != NULL)
+ tty_puts(tty, clr_eol);
+ else {
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ for (i = s->cx; i < screen_size_x(s); i++)
+ tty_putc(tty, ' ');
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ }
+}
+
+void
+tty_cmd_clearstartofline(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i;
+
+ tty_reset(tty);
+
+ if (clr_bol != NULL)
+ tty_puts(tty, clr_bol);
+ else {
+ tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ for (i = 0; i < s->cx + 1; i++)
+ tty_putc(tty, ' ');
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ }
+}
+
+void
+tty_cmd_cursormove(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua, ub;
+
+ ua = va_arg(ap, u_int);
+ ub = va_arg(ap, u_int);
+
+ tty_puts(tty, tparm(cursor_address, ub, ua));
+}
+
+void
+tty_cmd_cursormode(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ if (cursor_normal == NULL || cursor_invisible == NULL)
+ return;
+
+ ua = va_arg(ap, int);
+
+ if (ua && !(tty->flags & TTY_NOCURSOR))
+ tty_puts(tty, cursor_normal);
+ else
+ tty_puts(tty, cursor_invisible);
+}
+
+void
+tty_cmd_reverseindex(
+ struct tty *tty, unused struct screen *s, unused va_list ap)
+{
+ tty_reset(tty);
+ tty_puts(tty, scroll_reverse);
+}
+
+void
+tty_cmd_scrollregion(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua, ub;
+
+ ua = va_arg(ap, u_int);
+ ub = va_arg(ap, u_int);
+
+ tty_puts(tty, tparm(change_scroll_region, ua, ub));
+}
+
+void
+tty_cmd_insertmode(unused struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ if (enter_insert_mode == NULL || exit_insert_mode == NULL)
+ return;
+
+ ua = va_arg(ap, int);
+
+#if 0
+ if (ua)
+ tty_puts(tty, enter_insert_mode);
+ else
+ tty_puts(tty, exit_insert_mode);
+#endif
+}
+
+void
+tty_cmd_mousemode(struct tty *tty, unused struct screen *s, va_list ap)
+{
+ u_int ua;
+
+ if (key_mouse == NULL)
+ return;
+
+ ua = va_arg(ap, int);
+
+ if (ua)
+ tty_puts(tty, "\033[?1000h");
+ else
+ tty_puts(tty, "\033[?1000l");
+}
+
+void
+tty_cmd_linefeed(struct tty *tty, unused struct screen *s, unused va_list ap)
+{
+ tty_reset(tty);
+
+ tty_putc(tty, '\n');
+}
+
+void
+tty_cmd_carriagereturn(
+ struct tty *tty, unused struct screen *s, unused va_list ap)
+{
+ tty_reset(tty);
+
+ if (carriage_return)
+ tty_puts(tty, carriage_return);
+ else
+ tty_putc(tty, '\r');
+}
+
+void
+tty_cmd_bell(struct tty *tty, unused struct screen *s, unused va_list ap)
+{
+ if (bell)
+ tty_puts(tty, bell);
+}
+
+void
+tty_cmd_clearendofscreen(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i, j;
+
+ tty_reset(tty);
+
+ if (clr_eol != NULL) {
+ for (i = s->cy; i < screen_size_y(s); i++) {
tty_puts(tty, clr_eol);
- else {
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
- for (i = s->cx; i < screen_size_x(s); i++)
- tty_putc(tty, ' ');
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+ tty_puts(tty, cursor_down);
}
- break;
- case TTY_CLEARSTARTOFLINE:
- if (clr_bol != NULL)
- tty_puts(tty, clr_bol);
- else {
- tty_puts(tty, tparm(cursor_address, s->cy, 0));
- for (i = 0; i < s->cx + 1; i++)
+ } else {
+ for (i = s->cx; i < screen_size_y(s); i++)
+ tty_putc(tty, ' ');
+ for (j = s->cy; j < screen_size_y(s); j++) {
+ for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
- break;
- case TTY_CLEARLINE:
- if (clr_eol != NULL) {
- tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ }
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+}
+
+void
+tty_cmd_clearstartofscreen(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i, j;
+
+ tty_reset(tty);
+
+ tty_puts(tty, tparm(cursor_address, 0, 0));
+ if (clr_eol) {
+ for (i = 0; i < s->cy; i++)
tty_puts(tty, clr_eol);
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
- } else {
- tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ tty_puts(tty, tparm(cursor_address, s->cy, 0));
+ } else {
+ for (j = 0; j < s->cy; j++) {
for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
- }
- break;
- case TTY_INSERTLINE:
- ua = va_arg(ap, u_int);
- if (parm_insert_line != NULL)
- tty_puts(tty, tparm(parm_insert_line, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, insert_line);
- }
- break;
- case TTY_DELETELINE:
- ua = va_arg(ap, u_int);
- if (parm_delete_line != NULL)
- tty_puts(tty, tparm(parm_delete_line, ua));
- else {
- while (ua-- > 0)
- tty_puts(tty, delete_line);
+ }
+ }
+ for (i = 0; i < s->cx; i++)
+ tty_putc(tty, ' ');
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
+}
+
+void
+tty_cmd_clearscreen(struct tty *tty, struct screen *s, unused va_list ap)
+{
+ u_int i, j;
+
+ tty_reset(tty);
+
+ if (clr_eol) {
+ tty_puts(tty, tparm(cursor_address, 0, 0));
+ for (i = 0; i < screen_size_y(s); i++) {
+ tty_puts(tty, clr_eol);
+ tty_puts(tty, cursor_down);
}
- break;
- case TTY_INSERTCHARACTER:
- ua = va_arg(ap, u_int);
- if (parm_ich != NULL)
- tty_puts(tty, tparm(parm_ich, ua));
- else if (insert_character != NULL) {
- while (ua-- > 0)
- tty_puts(tty, insert_character);
- } else if (enter_insert_mode != NULL) {
- tty_puts(tty, enter_insert_mode);
- while (ua-- > 0)
+ } else {
+ tty_puts(tty, tparm(cursor_address, 0, 0));
+ for (j = 0; j < screen_size_y(s); j++) {
+ for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
- tty_puts(tty, exit_insert_mode);
- tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
- break;
- case TTY_DELETECHARACTER:
- ua = va_arg(ap, u_int);
- if (parm_dch != NULL)
- tty_puts(tty, tparm(parm_dch, ua));
- else if (delete_character != NULL) {
- while (ua-- > 0)
- tty_puts(tty, delete_character);
- } else {
- while (ua-- > 0)
- tty_putc(tty, '\010');
- }
- break;
- case TTY_CURSORON:
- if (!(tty->flags & TTY_NOCURSOR) && cursor_normal != NULL)
- tty_puts(tty, cursor_normal);
- break;
- case TTY_CURSOROFF:
- if (cursor_invisible != NULL)
- tty_puts(tty, cursor_invisible);
- break;
- case TTY_REVERSEINDEX:
- tty_puts(tty, scroll_reverse);
- break;
- case TTY_SCROLLREGION:
- ua = va_arg(ap, u_int);
- ub = va_arg(ap, u_int);
- tty_puts(tty, tparm(change_scroll_region, ua, ub));
- break;
-#if 0
- case TTY_INSERTON:
- if (enter_insert_mode != NULL)
- tty_puts(tty, enter_insert_mode);
- break;
- case TTY_INSERTOFF:
- if (exit_insert_mode != NULL)
- tty_puts(tty, exit_insert_mode);
- break;
-#endif
- case TTY_MOUSEOFF:
- if (key_mouse != NULL)
- tty_puts(tty, "\033[?1000l");
- break;
- case TTY_MOUSEON:
- if (key_mouse != NULL)
- tty_puts(tty, "\033[?1000h");
- break;
- case TTY_ATTRIBUTES:
- ua = va_arg(ap, u_int);
- ub = va_arg(ap, u_int);
- uc = va_arg(ap, u_int);
- tty_attributes(tty, ua, ub, uc);
- break;
}
+ tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
}
void
-tty_attributes(struct tty *tty, u_short attr, u_char fg, u_char bg)
+tty_cmd_cell(struct tty *tty, unused struct screen *s, va_list ap)
{
- if (attr == tty->attr && fg == tty->fg && bg == tty->bg)
+ struct grid_cell *gc;
+ u_int i, width;
+ u_char out[4];
+
+ gc = va_arg(ap, struct grid_cell *);
+
+ /* If this is a padding character, do nothing. */
+ if (gc->flags & GRID_FLAG_PADDING)
return;
- /* If any bits are being cleared, reset everything. */
- if (tty->attr & ~attr) {
- if ((tty->attr & ATTR_CHARSET) && exit_alt_charset_mode != NULL)
- tty_puts(tty, exit_alt_charset_mode);
- tty_puts(tty, exit_attribute_mode);
- tty->fg = 8;
- tty->bg = 8;
- tty->attr = 0;
+ /* Handle special characters. Should never come into this function.*/
+ if (gc->data < 0x20 || gc->data == 0x7f)
+ return;
+
+ /* Set the attributes. */
+ tty_attributes(tty, gc);
+
+ /* If not UTF8 multibyte, write directly. */
+ if (gc->data < 0xff) {
+ tty_putc(tty, gc->data);
+ return;
+ }
+
+ /* If the terminal doesn't support UTF8, write _s. */
+ if (!(tty->flags & TTY_UTF8)) {
+ width = utf8_width(gc->data);
+ while (width-- > 0)
+ tty_putc(tty, '_');
+ return;
+ }
+
+ /* Unpack UTF-8 and write it. */
+ utf8_split(gc->data, out);
+ for (i = 0; i < 4; i++) {
+ if (out[i] == 0xff)
+ break;
+ tty_putc(tty, out[i]);
}
+}
+
+void
+tty_reset(struct tty *tty)
+{
+ struct grid_cell *tc = &tty->cell;
+
+ tc->data = grid_default_cell.data;
+ if (memcmp(tc, &grid_default_cell, sizeof *tc) == 0)
+ return;
+
+ if (exit_alt_charset_mode != NULL && tc->attr & GRID_ATTR_CHARSET)
+ tty_puts(tty, exit_alt_charset_mode);
+ tty_puts(tty, exit_attribute_mode);
+ memcpy(tc, &grid_default_cell, sizeof *tc);
+}
+
+void
+tty_attributes(struct tty *tty, const struct grid_cell *gc)
+{
+ struct grid_cell *tc = &tty->cell;
+ u_char changed;
+
+ /* If any bits are being cleared, reset everything. */
+ if (tc->attr & ~gc->attr)
+ tty_reset(tty);
/* Filter out attribute bits already set. */
- attr &= ~tty->attr;
- tty->attr |= attr;
+ changed = gc->attr & ~tc->attr;
+ tc->attr = gc->attr;
/* Set the attributes. */
- if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL)
+ if ((changed & GRID_ATTR_BRIGHT) && enter_bold_mode != NULL)
tty_puts(tty, enter_bold_mode);
- if ((attr & ATTR_DIM) && enter_dim_mode != NULL)
+ if ((changed & GRID_ATTR_DIM) && enter_dim_mode != NULL)
tty_puts(tty, enter_dim_mode);
- if ((attr & ATTR_ITALICS) && enter_standout_mode != NULL)
+ if ((changed & GRID_ATTR_ITALICS) && enter_standout_mode != NULL)
tty_puts(tty, enter_standout_mode);
- if ((attr & ATTR_UNDERSCORE) && enter_underline_mode != NULL)
+ if ((changed & GRID_ATTR_UNDERSCORE) && enter_underline_mode != NULL)
tty_puts(tty, enter_underline_mode);
- if ((attr & ATTR_BLINK) && enter_blink_mode != NULL)
+ if ((changed & GRID_ATTR_BLINK) && enter_blink_mode != NULL)
tty_puts(tty, enter_blink_mode);
- if ((attr & ATTR_REVERSE) && enter_reverse_mode != NULL)
+ if ((changed & GRID_ATTR_REVERSE) && enter_reverse_mode != NULL)
tty_puts(tty, enter_reverse_mode);
- if ((attr & ATTR_HIDDEN) && enter_secure_mode != NULL)
+ if ((changed & GRID_ATTR_HIDDEN) && enter_secure_mode != NULL)
tty_puts(tty, enter_secure_mode);
- if ((attr & ATTR_CHARSET) && enter_alt_charset_mode != NULL)
+ if ((changed & GRID_ATTR_CHARSET) && enter_alt_charset_mode != NULL)
tty_puts(tty, enter_alt_charset_mode);
/* Set foreground colour. */
- if (fg != tty->fg || attr & ATTR_FG256)
- tty->fg = tty_attributes_fg(tty, fg);
-
+ if (gc->fg != tc->fg ||
+ (gc->flags & GRID_FLAG_FG256) != (tc->flags & GRID_FLAG_FG256)) {
+ tty_attributes_fg(tty, gc);
+ tc->fg = gc->fg;
+ }
+
/* Set background colour. */
- if (bg != tty->bg || attr & ATTR_BG256)
- tty->bg = tty_attributes_bg(tty, bg);
+ if (gc->bg != tc->bg ||
+ (gc->flags & GRID_FLAG_BG256) != (tc->flags & GRID_FLAG_BG256)) {
+ tty_attributes_bg(tty, gc);
+ tc->bg = gc->bg;
+ }
}
-u_char
-tty_attributes_fg(struct tty *tty, u_char fg)
+void
+tty_attributes_fg(struct tty *tty, const struct grid_cell *gc)
{
char s[32];
+ u_char fg = gc->fg;
- if (tty->attr & ATTR_FG256) {
- if (tty->term->flags & TERM_256COLOURS) {
+ if (gc->flags & GRID_FLAG_FG256) {
+ if ((tty->term->flags & TERM_256COLOURS) ||
+ (tty->term_flags & TERM_256COLOURS)) {
xsnprintf(s, sizeof s, "\033[38;5;%hhum", fg);
tty_puts(tty, s);
- return (fg);
+ return;
}
if (fg > 15)
@@ -715,25 +985,28 @@ tty_attributes_fg(struct tty *tty, u_char fg)
fg -= 8;
}
- if (fg == 8 && !(tty->term->flags & TERM_HASDEFAULTS))
+ if (fg == 8 &&
+ !(tty->term->flags & TERM_HASDEFAULTS) &&
+ !(tty->term_flags & TERM_HASDEFAULTS))
fg = 7;
if (fg == 8)
tty_puts(tty, "\033[39m");
else if (set_a_foreground != NULL)
tty_puts(tty, tparm(set_a_foreground, fg));
- return (fg);
}
-u_char
-tty_attributes_bg(struct tty *tty, u_char bg)
+void
+tty_attributes_bg(struct tty *tty, const struct grid_cell *gc)
{
char s[32];
+ u_char bg = gc->bg;
- if (tty->attr & ATTR_BG256) {
- if (tty->term->flags & TERM_256COLOURS) {
+ if (gc->flags & GRID_FLAG_BG256) {
+ if ((tty->term->flags & TERM_256COLOURS) ||
+ (tty->term_flags & TERM_256COLOURS)) {
xsnprintf(s, sizeof s, "\033[48;5;%hhum", bg);
tty_puts(tty, s);
- return (bg);
+ return;
}
if (bg > 15)
@@ -742,11 +1015,12 @@ tty_attributes_bg(struct tty *tty, u_char bg)
bg -= 8;
}
- if (bg == 8 && !(tty->term->flags & TERM_HASDEFAULTS))
+ if (bg == 8 &&
+ !(tty->term->flags & TERM_HASDEFAULTS) &&
+ !(tty->term_flags & TERM_HASDEFAULTS))
bg = 0;
if (bg == 8)
tty_puts(tty, "\033[49m");
else if (set_a_background != NULL)
tty_puts(tty, tparm(set_a_background, bg));
- return (bg);
}
diff --git a/utf8.c b/utf8.c
index 77179e77..5e1c6b94 100644
--- a/utf8.c
+++ b/utf8.c
@@ -1,4 +1,4 @@
-/* $Id: utf8.c,v 1.1 2008-09-09 22:16:37 nicm Exp $ */
+/* $Id: utf8.c,v 1.2 2008-09-25 20:08:56 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,93 +22,66 @@
#include "tmux.h"
-/*
- * UTF8 data structures. Just crappy array + linear search for now.
- */
-
-/* Pack UTF8 index into attr, data. */
-void
-utf8_pack(int idx, u_char *data, u_short *attr)
-{
- *data = idx & 0xff;
-
- *attr &= ~(ATTR_UTF8b8|ATTR_UTF8b9);
- if (idx & 0x100)
- *attr |= ATTR_UTF8b8;
- if (idx & 0x200)
- *attr |= ATTR_UTF8b9;
- if (idx & 0x400)
- *attr |= ATTR_UTF8b10;
- if (idx & 0x800)
- *attr |= ATTR_UTF8b11;
-}
-
-/* Unpack UTF8 index from attr, data. */
-int
-utf8_unpack(u_char data, u_short attr)
+u_int
+utf8_combine(const u_char data[4])
{
- int idx;
-
- idx = data;
- if (attr & ATTR_UTF8b8)
- idx |= 0x100;
- if (attr & ATTR_UTF8b9)
- idx |= 0x200;
- if (attr & ATTR_UTF8b10)
- idx |= 0x400;
- if (attr & ATTR_UTF8b11)
- idx |= 0x800;
-
- return (idx);
-}
-
-void
-utf8_init(struct utf8_table *utab, int limit)
-{
- utab->limit = limit;
- ARRAY_INIT(&utab->array);
+ u_int uv;
+
+ if (data[1] == 0xff)
+ uv = data[0];
+ else if (data[2] == 0xff) {
+ uv = data[1] & 0x3f;
+ uv |= (data[0] & 0x1f) << 6;
+ } else if (data[3] == 0xff) {
+ uv = data[2] & 0x3f;
+ uv |= (data[1] & 0x3f) << 6;
+ uv |= (data[0] & 0x0f) << 12;
+ } else {
+ uv = data[3] & 0x3f;
+ uv |= (data[2] & 0x3f) << 6;
+ uv |= (data[1] & 0x3f) << 12;
+ uv |= (data[0] & 0x3f) << 18;
+ }
+ return (uv);
}
void
-utf8_free(struct utf8_table *utab)
+utf8_split(u_int uv, u_char data[4])
{
- ARRAY_FREE(&utab->array);
-}
-
-struct utf8_data *
-utf8_lookup(struct utf8_table *utab, int idx)
-{
- if (idx < 0 || idx >= (int) ARRAY_LENGTH(&utab->array))
- return (NULL);
- return (&ARRAY_ITEM(&utab->array, idx));
-}
-
-int
-utf8_search(struct utf8_table *utab, struct utf8_data *udat)
-{
- u_int idx;
-
- for (idx = 0; idx < ARRAY_LENGTH(&utab->array); idx++) {
- if (memcmp(udat->data,
- ARRAY_ITEM(&utab->array, idx).data, sizeof udat->data) == 0)
- return (idx);
+ memset(data, 0xff, sizeof data);
+
+ if (uv <= 0x7f)
+ data[0] = uv;
+ else if (uv > 0x7f && uv <= 0x7ff) {
+ data[0] = (uv >> 6) | 0xc0;
+ data[1] = (uv & 0x3f) | 0x80;
+ } else if (uv > 0x7ff && uv <= 0xffff) {
+ data[0] = (uv >> 12) | 0xe0;
+ data[1] = ((uv >> 6) & 0x3f) | 0x80;
+ data[2] = (uv & 0x3f) | 0x80;
+ } else if (uv > 0xffff && uv <= 0x10ffff) {
+ data[0] = (uv >> 18) | 0xf0;
+ data[1] = ((uv >> 12) & 0x3f) | 0x80;
+ data[2] = ((uv >> 6) & 0x3f) | 0x80;
+ data[3] = (uv & 0x3f) | 0x80;
}
- return (-1);
}
int
-utf8_add(struct utf8_table *utab, struct utf8_data *udat)
+utf8_width(u_int uv)
{
- int idx;
-
- if (ARRAY_LENGTH(&utab->array) == utab->limit)
- return (-1);
-
- if ((idx = utf8_search(utab, udat)) != -1)
- return (idx);
-
- ARRAY_EXPAND(&utab->array, 1);
- memcpy(
- &ARRAY_LAST(&utab->array), udat, sizeof ARRAY_LAST(&utab->array));
- return (ARRAY_LENGTH(&utab->array) - 1);
+ if ((uv >= 0x1100 && uv <= 0x115f) ||
+ uv == 0x2329 ||
+ uv == 0x232a ||
+ (uv >= 0x2e80 && uv <= 0xa4cf && uv != 0x303f) ||
+ (uv >= 0xac00 && uv <= 0xd7a3) ||
+ (uv >= 0xf900 && uv <= 0xfaff) ||
+ (uv >= 0xfe10 && uv <= 0xfe19) ||
+ (uv >= 0xfe30 && uv <= 0xfe6f) ||
+ (uv >= 0xff00 && uv <= 0xff60) ||
+ (uv >= 0xffe0 && uv <= 0xffe6) ||
+ (uv >= 0x20000 && uv <= 0x2fffd) ||
+ (uv >= 0x30000 && uv <= 0x3fffd))
+ return (2);
+ return (1);
}
diff --git a/window-copy.c b/window-copy.c
index 51d53e4a..27486ce9 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -1,4 +1,4 @@
-/* $Id: window-copy.c,v 1.30 2008-09-10 19:15:04 nicm Exp $ */
+/* $Id: window-copy.c,v 1.31 2008-09-25 20:08:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -44,6 +44,7 @@ int window_copy_update_selection(struct window *);
void window_copy_copy_selection(struct window *, struct client *);
void window_copy_copy_line(
struct window *, char **, size_t *, u_int, u_int, u_int);
+int window_copy_is_space(struct window *, u_int, u_int);
u_int window_copy_find_length(struct window *, u_int);
void window_copy_cursor_start_of_line(struct window *);
void window_copy_cursor_end_of_line(struct window *);
@@ -58,10 +59,6 @@ void window_copy_scroll_right(struct window *, u_int);
void window_copy_scroll_up(struct window *, u_int);
void window_copy_scroll_down(struct window *, u_int);
-const char *space_characters = " -_@";
-#define window_copy_is_space(w, x, y) \
- (strchr(space_characters, (w)->base.grid_data[y][x]) != NULL)
-
const struct window_mode window_copy_mode = {
window_copy_init,
window_copy_free,
@@ -104,7 +101,7 @@ window_copy_init(struct window *w)
screen_write_start(&ctx, s, NULL, NULL);
for (i = 0; i < screen_size_y(s); i++)
window_copy_write_line(w, &ctx, i);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
return (s);
@@ -124,10 +121,12 @@ window_copy_resize(struct window *w, u_int sx, u_int sy)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
+ struct screen_write_ctx ctx;
screen_resize(s, sx, sy);
- screen_display_copy_area(&data->screen, &w->base,
- 0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
+ screen_write_start(&ctx, s, NULL, NULL);
+ window_copy_write_lines(w, &ctx, 0, screen_size_y(s) - 1);
+ screen_write_stop(&ctx);
window_copy_update_selection(w);
}
@@ -156,8 +155,8 @@ window_copy_key(struct window *w, struct client *c, int key)
window_copy_cursor_down(w);
return;
case MODEKEY_PPAGE:
- if (data->oy + screen_size_y(s) > w->base.hsize)
- data->oy = w->base.hsize;
+ if (data->oy + screen_size_y(s) > screen_hsize(&w->base))
+ data->oy = screen_hsize(&w->base);
else
data->oy += screen_size_y(s);
window_copy_update_selection(w);
@@ -202,44 +201,38 @@ window_copy_key(struct window *w, struct client *c, int key)
}
void
-window_copy_write_line(
- struct window *w, struct screen_write_ctx *ctx, u_int py)
+window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
{
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
+ struct grid_cell gc;
+ char hdr[32];
size_t size;
if (py == 0) {
- screen_write_set_attributes(
- ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
- screen_write_move_cursor(ctx, 0, 0);
- size = screen_write_put_string_rjust(
- ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
- screen_write_set_attributes(ctx, 0, 8, 8);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ size = xsnprintf(hdr, sizeof hdr,
+ "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base));
+ gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
+ screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
+ screen_write_puts(ctx, &gc, "%s", hdr);
+ gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
} else
size = 0;
- screen_write_move_cursor(ctx, 0, py);
- screen_write_copy_area(
- ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
+
+ screen_write_cursormove(ctx, 0, py);
+ screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) -
+ data->oy) + py, screen_size_x(s) - size, 1);
}
void
window_copy_write_lines(
struct window *w, struct screen_write_ctx *ctx, u_int py, u_int ny)
{
- struct window_copy_mode_data *data = w->modedata;
- struct screen *s = &data->screen;
+ u_int yy;
- if (py == 0) {
- window_copy_write_line(w, ctx, 0);
- if (ny == 1)
- return;
- py++;
- ny--;
- }
- screen_write_move_cursor(ctx, 0, py);
- screen_write_copy_area(
- ctx, &w->base, screen_size_x(s), ny, data->ox, data->oy);
+ for (yy = py; yy < py + ny; yy++)
+ window_copy_write_line(w, ctx, py);
}
void
@@ -249,21 +242,19 @@ window_copy_write_column(
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
- screen_write_move_cursor(ctx, px, 0);
- screen_write_copy_area(
- ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
+ screen_write_cursormove(ctx, px, 0);
+ screen_write_copy(ctx, &w->base,
+ data->ox, screen_hsize(&w->base) - data->oy, 1, screen_size_y(s));
}
void
window_copy_write_columns(
struct window *w, struct screen_write_ctx *ctx, u_int px, u_int nx)
{
- struct window_copy_mode_data *data = w->modedata;
- struct screen *s = &data->screen;
+ u_int xx;
- screen_write_move_cursor(ctx, px, 0);
- screen_write_copy_area(
- ctx, &w->base, nx, screen_size_y(s), data->ox, data->oy);
+ for (xx = px; xx < px + nx; xx++)
+ window_copy_write_column(w, ctx, px);
}
void
@@ -276,7 +267,7 @@ window_copy_redraw_lines(struct window *w, u_int py, u_int ny)
screen_write_start_window(&ctx, w);
for (i = py; i < py + ny; i++)
window_copy_write_line(w, &ctx, i);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
@@ -295,7 +286,7 @@ window_copy_update_cursor(struct window *w)
struct screen_write_ctx ctx;
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
@@ -305,8 +296,8 @@ window_copy_start_selection(struct window *w)
struct window_copy_mode_data *data = w->modedata;
struct screen *s = &data->screen;
- data->selx = screen_x(&w->base, data->cx) + data->ox;
- data->sely = screen_y(&w->base, data->cy) - data->oy;
+ data->selx = data->cx + data->ox;
+ data->sely = screen_hsize(&w->base) + data->cy - data->oy;
s->sel.flag = 1;
window_copy_update_selection(w);
@@ -323,8 +314,8 @@ window_copy_update_selection(struct window *w)
return (0);
/* Find top-left of screen. */
- tx = screen_x(&w->base, 0) + data->ox;
- ty = screen_y(&w->base, 0) - data->oy;
+ tx = data->ox;
+ ty = screen_hsize(&w->base) - data->oy;
/* Adjust the selection. */
sx = data->selx;
@@ -333,28 +324,26 @@ window_copy_update_selection(struct window *w)
/* Above it. */
sx = 0;
sy = 0;
- } else if (sy > ty + screen_last_y(s)) {
+ } else if (sy > ty + screen_size_y(s) - 1) {
/* Below it. */
- sx = screen_last_x(s);
- sy = screen_last_y(s);
+ sx = screen_size_x(s) - 1;
+ sy = screen_size_y(s) - 1;
} else if (sx < tx) {
/* To the left. */
sx = 0;
- } else if (sx > tx + screen_last_x(s)) {
+ } else if (sx > tx + screen_size_x(s) - 1) {
/* To the right. */
sx = 0;
sy++;
- if (sy > screen_last_y(s))
- sy = screen_last_y(s);
+ if (sy > screen_size_y(s) - 1)
+ sy = screen_size_y(s) - 1;
} else {
sx -= tx;
sy -= ty;
}
- sx = screen_x(s, sx);
- sy = screen_x(s, sy);
+ sy = screen_hsize(s) + sy;
- screen_set_selection(
- s, sx, sy, screen_x(s, data->cx), screen_y(s, data->cy));
+ screen_set_selection(s, sx, sy, data->cx, screen_hsize(s) + data->cy);
return (1);
}
@@ -381,8 +370,8 @@ window_copy_copy_selection(struct window *w, struct client *c)
*/
/* Find start and end. */
- xx = screen_x(&w->base, data->cx) + data->ox;
- yy = screen_y(&w->base, data->cy) - data->oy;
+ xx = data->cx + data->ox;
+ yy = screen_hsize(&w->base) + data->cy - data->oy;
if (xx < data->selx || (yy == data->sely && xx < data->selx)) {
sx = xx; sy = yy;
ex = data->selx; ey = data->sely;
@@ -425,7 +414,8 @@ void
window_copy_copy_line(
struct window *w, char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
{
- u_char i, xx;
+ const struct grid_cell *gc;
+ u_char i, j, xx, data[4];
if (sx > ex)
return;
@@ -438,9 +428,15 @@ window_copy_copy_line(
if (sx < ex) {
for (i = sx; i < ex; i++) {
- *buf = xrealloc(*buf, 1, (*off) + 1);
- (*buf)[*off] = w->base.grid_data[sy][i];
- (*off)++;
+ gc = grid_peek_cell(w->base.grid, i, sy);
+ utf8_split(gc->data, data);
+
+ *buf = xrealloc(*buf, 1, (*off) + 4);
+ for (j = 0; j < sizeof data; j++) {
+ if (data[j] == 0xff)
+ break;
+ (*buf)[(*off)++] = data[j];
+ }
}
}
@@ -449,14 +445,33 @@ window_copy_copy_line(
(*off)++;
}
+int
+window_copy_is_space(struct window *w, u_int px, u_int py)
+{
+ const struct grid_cell *gc;
+ const char *spaces = " -_@";
+
+ gc = grid_peek_cell(w->base.grid, px, py);
+ if (gc->flags & GRID_FLAG_PADDING)
+ return (0);
+ if (gc->data == 0x00 || gc->data > 0xff)
+ return (0);
+ return (strchr(spaces, gc->data) != NULL);
+}
+
u_int
window_copy_find_length(struct window *w, u_int py)
{
- u_int px;
-
- px = w->base.grid_size[py];
- while (px > 0 && w->base.grid_data[py][px - 1] == ' ')
+ const struct grid_cell *gc;
+ u_int px;
+
+ px = w->base.grid->size[py];
+ while (px > 0) {
+ gc = grid_peek_cell(w->base.grid, px - 1, py);
+ if (gc->data != 0x20)
+ break;
px--;
+ }
return (px);
}
@@ -482,32 +497,32 @@ window_copy_cursor_end_of_line(struct window *w)
struct screen *s = &data->screen;
u_int px, py;
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
px = window_copy_find_length(w, py);
/* On screen. */
- if (px > data->ox && px <= data->ox + screen_last_x(s))
+ if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
data->cx = px - data->ox;
/* Off right of screen. */
- if (px > data->ox + screen_last_x(s)) {
+ if (px > data->ox + screen_size_x(s) - 1) {
/* Move cursor to last and scroll screen. */
- window_copy_scroll_left(w,
- px - data->ox - screen_last_x(s));
- data->cx = screen_last_x(s);
+ window_copy_scroll_left(
+ w, px - data->ox - (screen_size_x(s) - 1));
+ data->cx = screen_size_x(s) - 1;
}
/* Off left of screen. */
if (px <= data->ox) {
- if (px < screen_last_x(s)) {
+ if (px < screen_size_x(s) - 1) {
/* Short enough to fit on screen. */
window_copy_scroll_right(w, data->ox);
data->cx = px;
} else {
/* Too long to fit on screen. */
window_copy_scroll_right(
- w, data->ox - (px - screen_last_x(s)));
- data->cx = screen_last_x(s);
+ w, data->ox - (px - (screen_size_x(s) - 1)));
+ data->cx = screen_size_x(s) - 1;
}
}
@@ -544,7 +559,7 @@ window_copy_cursor_right(struct window *w)
struct window_copy_mode_data *data = w->modedata;
u_int px, py;
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
px = window_copy_find_length(w, py);
if (data->cx >= px) {
@@ -565,7 +580,7 @@ window_copy_cursor_up(struct window *w)
struct window_copy_mode_data *data = w->modedata;
u_int ox, oy, px, py;
- oy = screen_y(&w->base, data->cy) - data->oy;
+ oy = screen_hsize(&w->base) + data->cy - data->oy;
ox = window_copy_find_length(w, oy);
if (data->cy == 0)
@@ -578,7 +593,7 @@ window_copy_cursor_up(struct window *w)
window_copy_update_cursor(w);
}
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
px = window_copy_find_length(w, py);
if (data->cx + data->ox >= px || data->cx + data->ox >= ox)
@@ -592,10 +607,10 @@ window_copy_cursor_down(struct window *w)
struct screen *s = &data->screen;
u_int ox, oy, px, py;
- oy = screen_y(&w->base, data->cy) - data->oy;
+ oy = screen_hsize(&w->base) + data->cy - data->oy;
ox = window_copy_find_length(w, oy);
- if (data->cy == screen_last_y(s))
+ if (data->cy == screen_size_y(s) - 1)
window_copy_scroll_up(w, 1);
else {
data->cy++;
@@ -605,7 +620,7 @@ window_copy_cursor_down(struct window *w)
window_copy_update_cursor(w);
}
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
px = window_copy_find_length(w, py);
if (data->cx + data->ox >= px || data->cx + data->ox >= ox)
@@ -620,7 +635,7 @@ window_copy_cursor_next_word(struct window *w)
u_int px, py, xx, skip;
px = data->ox + data->cx;
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
xx = window_copy_find_length(w, py);
skip = 1;
@@ -638,7 +653,7 @@ window_copy_cursor_next_word(struct window *w)
}
while (px >= xx) {
- if (data->cy == screen_last_y(s)) {
+ if (data->cy == screen_size_y(s) - 1) {
if (data->oy == 0)
goto out;
}
@@ -646,7 +661,8 @@ window_copy_cursor_next_word(struct window *w)
px = 0;
window_copy_cursor_down(w);
- py = screen_y(&w->base, data->cy) - data->oy;
+ py =screen_hsize(
+ &w->base) + data->cy - data->oy;
xx = window_copy_find_length(w, py);
}
}
@@ -666,28 +682,28 @@ window_copy_cursor_next_word(struct window *w)
out:
/* On screen. */
- if (px > data->ox && px <= data->ox + screen_last_x(s))
+ if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
data->cx = px - data->ox;
/* Off right of screen. */
- if (px > data->ox + screen_last_x(s)) {
+ if (px > data->ox + screen_size_x(s) - 1) {
/* Move cursor to last and scroll screen. */
- window_copy_scroll_left(w,
- px - data->ox - screen_last_x(s));
- data->cx = screen_last_x(s);
+ window_copy_scroll_left(
+ w, px - data->ox - (screen_size_x(s) - 1));
+ data->cx = screen_size_x(s) - 1;
}
/* Off left of screen. */
if (px <= data->ox) {
- if (px < screen_last_x(s)) {
+ if (px < screen_size_x(s) - 1) {
/* Short enough to fit on screen. */
window_copy_scroll_right(w, data->ox);
data->cx = px;
} else {
/* Too long to fit on screen. */
window_copy_scroll_right(
- w, data->ox - (px - screen_last_x(s)));
- data->cx = screen_last_x(s);
+ w, data->ox - (px - (screen_size_x(s) - 1)));
+ data->cx = screen_size_x(s) - 1;
}
}
@@ -705,7 +721,7 @@ window_copy_cursor_previous_word(struct window *w)
u_int ox, px, py, skip;
ox = px = data->ox + data->cx;
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(&w->base) + data->cy - data->oy;
skip = 1;
if (px != 0) {
@@ -719,13 +735,15 @@ window_copy_cursor_previous_word(struct window *w)
break;
while (px == 0) {
- if (data->cy == 0 && (w->base.hsize == 0 ||
- data->oy >= w->base.hsize - 1))
+ if (data->cy == 0 &&
+ (screen_hsize(&w->base) == 0 ||
+ data->oy >= screen_hsize(&w->base) - 1))
goto out;
window_copy_cursor_up(w);
- py = screen_y(&w->base, data->cy) - data->oy;
+ py = screen_hsize(
+ &w->base) + data->cy - data->oy;
px = window_copy_find_length(w, py);
}
goto out;
@@ -746,28 +764,28 @@ window_copy_cursor_previous_word(struct window *w)
out:
/* On screen. */
- if (px > data->ox && px <= data->ox + screen_last_x(s))
+ if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
data->cx = px - data->ox;
/* Off right of screen. */
- if (px > data->ox + screen_last_x(s)) {
+ if (px > data->ox + screen_size_x(s) - 1) {
/* Move cursor to last and scroll screen. */
- window_copy_scroll_left(w,
- px - data->ox - screen_last_x(s));
- data->cx = screen_last_x(s);
+ window_copy_scroll_left(
+ w, px - data->ox - (screen_size_x(s) - 1));
+ data->cx = screen_size_x(s) - 1;
}
/* Off left of screen. */
if (px <= data->ox) {
- if (px < screen_last_x(s)) {
+ if (px < screen_size_x(s) - 1) {
/* Short enough to fit on screen. */
window_copy_scroll_right(w, data->ox);
data->cx = px;
} else {
/* Too long to fit on screen. */
window_copy_scroll_right(
- w, data->ox - (px - screen_last_x(s)));
- data->cx = screen_last_x(s);
+ w, data->ox - (px - (screen_size_x(s) - 1)));
+ data->cx = screen_size_x(s) - 1;
}
}
@@ -794,8 +812,8 @@ window_copy_scroll_left(struct window *w, u_int nx)
screen_write_start_window(&ctx, w);
for (i = 1; i < screen_size_y(s); i++) {
- screen_write_move_cursor(&ctx, 0, i);
- screen_write_delete_characters(&ctx, nx);
+ screen_write_cursormove(&ctx, 0, i);
+ screen_write_deletecharacter(&ctx, nx);
}
window_copy_write_columns(w, &ctx, screen_size_x(s) - nx, nx);
window_copy_write_line(w, &ctx, 0);
@@ -803,7 +821,7 @@ window_copy_scroll_left(struct window *w, u_int nx)
window_copy_update_selection(w);
window_copy_write_lines(w, &ctx, data->cy, 1);
}
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
@@ -824,14 +842,14 @@ window_copy_scroll_right(struct window *w, u_int nx)
screen_write_start_window(&ctx, w);
for (i = 1; i < screen_size_y(s); i++) {
- screen_write_move_cursor(&ctx, 0, i);
- screen_write_insert_characters(&ctx, nx);
+ screen_write_cursormove(&ctx, 0, i);
+ screen_write_insertcharacter(&ctx, nx);
}
window_copy_write_columns(w, &ctx, 0, nx);
window_copy_write_line(w, &ctx, 0);
if (s->sel.flag)
- window_copy_write_lines(w, &ctx, data->cy, 1);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ window_copy_write_line(w, &ctx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
@@ -850,13 +868,13 @@ window_copy_scroll_up(struct window *w, u_int ny)
window_copy_update_selection(w);
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_delete_lines(&ctx, ny);
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_deleteline(&ctx, ny);
window_copy_write_lines(w, &ctx, screen_size_y(s) - ny, ny);
window_copy_write_line(w, &ctx, 0);
if (s->sel.flag && screen_size_y(s) > ny)
- window_copy_write_lines(w, &ctx, screen_size_y(s) - ny - 1, 1);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ window_copy_write_line(w, &ctx, screen_size_y(s) - ny - 1);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
@@ -867,24 +885,24 @@ window_copy_scroll_down(struct window *w, u_int ny)
struct screen *s = &data->screen;
struct screen_write_ctx ctx;
- if (ny > w->base.hsize)
+ if (ny > screen_hsize(&w->base))
return;
- if (data->oy > w->base.hsize - ny)
- ny = w->base.hsize - data->oy;
+ if (data->oy > screen_hsize(&w->base) - ny)
+ ny = screen_hsize(&w->base) - data->oy;
if (ny == 0)
return;
data->oy += ny;
window_copy_update_selection(w);
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_insert_lines(&ctx, ny);
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_insertline(&ctx, ny);
window_copy_write_lines(w, &ctx, 0, ny);
if (s->sel.flag && screen_size_y(s) > ny)
- window_copy_write_lines(w, &ctx, ny, 1);
+ window_copy_write_line(w, &ctx, ny);
else if (ny == 1) /* nuke position */
window_copy_write_line(w, &ctx, 1);
- screen_write_move_cursor(&ctx, data->cx, data->cy);
+ screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
diff --git a/window-more.c b/window-more.c
index 65a926ed..1bda266c 100644
--- a/window-more.c
+++ b/window-more.c
@@ -1,4 +1,4 @@
-/* $Id: window-more.c,v 1.18 2008-09-10 19:15:04 nicm Exp $ */
+/* $Id: window-more.c,v 1.19 2008-09-25 20:08:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -62,7 +62,7 @@ window_more_vadd(struct window *w, const char *fmt, va_list ap)
screen_write_start_window(&ctx, w);
size = ARRAY_LENGTH(&data->list) - 1;
- if (size >= data->top && size <= data->top + screen_last_y(s)) {
+ if (size >= data->top && size <= data->top + screen_size_y(s) - 1) {
window_more_write_line(w, &ctx, size - data->top);
if (size != data->top)
window_more_write_line(w, &ctx, 0);
@@ -164,27 +164,30 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
{
struct window_more_mode_data *data = w->modedata;
struct screen *s = &data->screen;
- char *msg;
+ struct grid_cell gc;
+ char *msg, hdr[32];
size_t size;
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+
if (py == 0) {
- screen_write_set_attributes(
- ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
- screen_write_move_cursor(ctx, 0, 0);
- size = screen_write_put_string_rjust(
- ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
+ size = xsnprintf(hdr, sizeof hdr,
+ "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
+ screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
+ gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
+ screen_write_puts(ctx, &gc, "%s", hdr);
+ gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
} else
size = 0;
- screen_write_set_attributes(ctx, 0, 8, 8);
- screen_write_move_cursor(ctx, 0, py);
+ screen_write_cursormove(ctx, 0, py);
if (data->top + py < ARRAY_LENGTH(&data->list)) {
msg = ARRAY_ITEM(&data->list, data->top + py);
- screen_write_put_string(
- ctx, "%.*s", (int) (screen_size_x(s) - size), msg);
+ screen_write_puts(
+ ctx, &gc, "%.*s", (int) (screen_size_x(s) - size), msg);
}
while (s->cx < screen_size_x(s) - size)
- screen_write_put_character(ctx, ' ');
+ screen_write_putc(ctx, &gc, ' ');
}
void
@@ -212,8 +215,8 @@ window_more_scroll_up(struct window *w)
data->top--;
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_insert_lines(&ctx, 1);
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_insertline(&ctx, 1);
window_more_write_line(w, &ctx, 0);
window_more_write_line(w, &ctx, 1);
screen_write_stop(&ctx);
@@ -231,9 +234,9 @@ window_more_scroll_down(struct window *w)
data->top++;
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_delete_lines(&ctx, 1);
- window_more_write_line(w, &ctx, screen_last_y(s));
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_deleteline(&ctx, 1);
+ window_more_write_line(w, &ctx, screen_size_y(s) - 1);
window_more_write_line(w, &ctx, 0);
screen_write_stop(&ctx);
}
diff --git a/window-scroll.c b/window-scroll.c
index 09f5b1e7..210f66f2 100644
--- a/window-scroll.c
+++ b/window-scroll.c
@@ -1,4 +1,4 @@
-/* $Id: window-scroll.c,v 1.23 2008-09-10 19:15:05 nicm Exp $ */
+/* $Id: window-scroll.c,v 1.24 2008-09-25 20:08:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -90,10 +90,14 @@ window_scroll_resize(struct window *w, u_int sx, u_int sy)
{
struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &data->screen;
+ struct screen_write_ctx ctx;
+ u_int i;
screen_resize(s, sx, sy);
- screen_display_copy_area(&data->screen, &w->base,
- 0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
+ screen_write_start(&ctx, s, NULL, NULL);
+ for (i = 0; i < screen_size_y(s); i++)
+ window_scroll_write_line(w, &ctx, i);
+ screen_write_stop(&ctx);
}
void
@@ -121,8 +125,8 @@ window_scroll_key(struct window *w, struct client *c, int key)
window_scroll_scroll_down(w);
break;
case MODEKEY_PPAGE:
- if (data->oy + screen_size_y(s) > w->base.hsize)
- data->oy = w->base.hsize;
+ if (data->oy + screen_size_y(s) > screen_hsize(&w->base))
+ data->oy = screen_hsize(&w->base);
else
data->oy += screen_size_y(s);
window_scroll_redraw_screen(w);
@@ -145,19 +149,24 @@ window_scroll_write_line(
{
struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &data->screen;
+ struct grid_cell gc;
+ char hdr[32];
size_t size;
if (py == 0) {
- screen_write_set_attributes(
- ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
- screen_write_move_cursor(ctx, 0, 0);
- size = screen_write_put_string_rjust(
- ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ size = xsnprintf(hdr, sizeof hdr,
+ "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base));
+ gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
+ screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
+ screen_write_puts(ctx, &gc, "%s", hdr);
+ gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
} else
size = 0;
- screen_write_move_cursor(ctx, 0, py);
- screen_write_copy_area(
- ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
+
+ screen_write_cursormove(ctx, 0, py);
+ screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) -
+ data->oy) + py, screen_size_x(s) - size, 1);
}
void
@@ -167,9 +176,9 @@ window_scroll_write_column(
struct window_scroll_mode_data *data = w->modedata;
struct screen *s = &data->screen;
- screen_write_move_cursor(ctx, px, 0);
- screen_write_copy_area(
- ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
+ screen_write_cursormove(ctx, px, 0);
+ screen_write_copy(ctx, &w->base, data->ox + px,
+ screen_hsize(&w->base) - data->oy, 1, screen_size_y(s));
}
void
@@ -192,13 +201,13 @@ window_scroll_scroll_up(struct window *w)
struct window_scroll_mode_data *data = w->modedata;
struct screen_write_ctx ctx;
- if (data->oy >= w->base.hsize)
+ if (data->oy >= screen_hsize(&w->base))
return;
data->oy++;
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_insert_lines(&ctx, 1);
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_insertline(&ctx, 1);
window_scroll_write_line(w, &ctx, 0);
window_scroll_write_line(w, &ctx, 1);
screen_write_stop(&ctx);
@@ -216,9 +225,9 @@ window_scroll_scroll_down(struct window *w)
data->oy--;
screen_write_start_window(&ctx, w);
- screen_write_move_cursor(&ctx, 0, 0);
- screen_write_delete_lines(&ctx, 1);
- window_scroll_write_line(w, &ctx, screen_last_y(s));
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_deleteline(&ctx, 1);
+ window_scroll_write_line(w, &ctx, screen_size_y(s) - 1);
window_scroll_write_line(w, &ctx, 0);
screen_write_stop(&ctx);
}
@@ -237,10 +246,10 @@ window_scroll_scroll_right(struct window *w)
screen_write_start_window(&ctx, w);
for (i = 1; i < screen_size_y(s); i++) {
- screen_write_move_cursor(&ctx, 0, i);
- screen_write_delete_characters(&ctx, 1);
+ screen_write_cursormove(&ctx, 0, i);
+ screen_write_deletecharacter(&ctx, 1);
}
- window_scroll_write_column(w, &ctx, screen_last_x(s));
+ window_scroll_write_column(w, &ctx, screen_size_x(s) - 1);
window_scroll_write_line(w, &ctx, 0);
screen_write_stop(&ctx);
}
@@ -259,8 +268,8 @@ window_scroll_scroll_left(struct window *w)
screen_write_start_window(&ctx, w);
for (i = 1; i < screen_size_y(s); i++) {
- screen_write_move_cursor(&ctx, 0, i);
- screen_write_insert_characters(&ctx, 1);
+ screen_write_cursormove(&ctx, 0, i);
+ screen_write_insertcharacter(&ctx, 1);
}
window_scroll_write_column(w, &ctx, 0);
window_scroll_write_line(w, &ctx, 0);