diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-12-06 09:46:23 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-12-06 09:46:23 +0000 |
commit | 103748d6adfe1b2d706cb0a1e1a128be5366d655 (patch) | |
tree | b9d4feef5012083d9c0ba96693322286645a27a3 /screen-write.c | |
parent | 6f142e9ac61783e79c27e56ed6aa2fc7ff13683d (diff) |
Major reorganisation of screen handling.
Diffstat (limited to 'screen-write.c')
-rw-r--r-- | screen-write.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/screen-write.c b/screen-write.c new file mode 100644 index 00000000..c033a782 --- /dev/null +++ b/screen-write.c @@ -0,0 +1,516 @@ +/* $Id: screen-write.c,v 1.1 2007-12-06 09:46:23 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <string.h> + +#include "tmux.h" + +#define screen_write_limit(v, lower, upper) do { \ + if (v < lower) \ + v = lower; \ + if (v > upper) \ + v = upper; \ +} while (0) + +/* Initialise writing with a window. */ +void +screen_write_start_window(struct screen_write_ctx *ctx, struct window *w) +{ + struct screen *t = w->screen; + + screen_write_start(ctx, t, tty_write_window, w); +} + +/* Initialise writing with a client. */ +void +screen_write_start_client(struct screen_write_ctx *ctx, struct client *c) +{ + struct screen *t = c->session->curw->window->screen; + + screen_write_start(ctx, t, tty_write_client, c); +} + +/* Initialise writing with a session. */ +void +screen_write_start_session(struct screen_write_ctx *ctx, struct session *s) +{ + struct screen *t = s->curw->window->screen; + + screen_write_start(ctx, t, tty_write_session, s); +} + +/* Initialise writing. */ +void +screen_write_start(struct screen_write_ctx *ctx, + struct screen *s, void (*write)(void *, int, ...), void *data) +{ + ctx->write = write; + ctx->data = data; + + ctx->s = s; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSOROFF); +} + +/* Finalise writing. */ +void +screen_write_stop(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + if (ctx->write != NULL && s->mode & MODE_CURSOR) + ctx->write(ctx->data, TTY_CURSORON); +} + +/* Set screen title. */ +void +screen_write_set_title(struct screen_write_ctx *ctx, char *title) +{ + struct screen *s = ctx->s; + + xfree(s->title); + s->title = title; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_TITLE, s->title); +} + +/* Put a character. */ +void +screen_write_put_character(struct screen_write_ctx *ctx, u_char ch) +{ + struct screen *s = ctx->s; + + if (s->cx == screen_size_x(s)) { + s->cx = 0; + screen_write_cursor_down_scroll(ctx); + } else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) + return; + + screen_display_set_cell(s, s->cx, s->cy, ch, s->attr, s->colr); + s->cx++; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CHARACTER, ch); +} + +/* Put a string right-justified. */ +size_t printflike2 +screen_write_put_string_rjust( + struct screen_write_ctx *ctx, const char *fmt, ...) +{ + struct screen *s = ctx->s; + va_list ap; + size_t size; + char *msg, *ptr; + + va_start(ap, fmt); + size = vasprintf(&msg, fmt, ap); + va_end(ap); + + ptr = msg; + if (size > screen_size_x(s)) { + ptr += size - screen_size_x(s); + size = screen_size_x(s); + } + screen_write_move_cursor(ctx, screen_size_x(s) - size, s->cy); + for (; *ptr != '\0'; ptr++) { + if (s->cx == screen_size_x(s)) + break; + screen_write_put_character(ctx, *ptr); + } + + xfree(msg); + + return (size); +} + +/* Put a string, truncating at end of line. */ +void printflike2 +screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...) +{ + struct screen *s = ctx->s; + va_list ap; + char *msg, *ptr; + + va_start(ap, fmt); + vasprintf(&msg, fmt, ap); + va_end(ap); + + for (ptr = msg; *ptr != '\0'; ptr++) { + if (s->cx == screen_size_x(s)) + break; + screen_write_put_character(ctx, *ptr); + } + + xfree(msg); +} + +/* Set screen attributes. */ +void +screen_write_set_attributes( + struct screen_write_ctx *ctx, u_char attr, u_char colr) +{ + struct screen *s = ctx->s; + + if (s->attr != attr || s->colr != colr) { + s->attr = attr; + s->colr = colr; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); + } +} + +/* Set scroll region. */ +void +screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower) +{ + struct screen *s = ctx->s; + + screen_write_limit(upper, 0, screen_last_y(s)); + screen_write_limit(lower, 0, screen_last_y(s)); + if (upper > lower) + return; + + /* Cursor moves to top-left. */ + s->cx = 0; + s->cy = upper; + + s->rupper = upper; + s->rlower = lower; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); +} + +/* Move cursor up and scroll if necessary. */ +void +screen_write_cursor_up_scroll(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + if (s->cy == s->rupper) + screen_display_scroll_region_down(s); + else if (s->cy > 0) + s->cy--; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_REVERSEINDEX); +} + +/* Move cursor down and scroll if necessary */ +void +screen_write_cursor_down_scroll(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + if (s->cy == s->rlower) + screen_display_scroll_region_up(s); + else if (s->cy < screen_last_y(s)) + s->cy++; + + if (ctx->write != NULL) /* XXX FORWARDINDEX */ + ctx->write(ctx->data, TTY_CHARACTER, '\n'); +} + +/* Move cursor up. */ +void +screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_above_y(s, s->cy) - 1); + + s->cy -= n; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); +} + +/* Move cursor down. */ +void +screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_below_y(s, s->cy) - 1); + + s->cy += n; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); +} + +/* Move cursor left. */ +void +screen_write_cursor_left(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_left_x(s, s->cx) - 1); + + s->cx -= n; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); +} + +/* Move cursor right. */ +void +screen_write_cursor_right(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_right_x(s, s->cx) - 1); + + s->cx += n; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); +} + +/* Delete lines. */ +void +screen_write_delete_lines(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_below_y(s, s->cy)); + + if (s->cy < s->rupper || s->cy > s->rlower) + screen_display_delete_lines(s, s->cy, n); + else + screen_display_delete_lines_region(s, s->cy, n); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_DELETELINE, n); +} + +/* Delete characters. */ +void +screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_right_x(s, s->cx)); + + screen_display_delete_characters(s, s->cx, s->cy, n); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_DELETECHARACTER, n); +} + +/* Insert lines. */ +void +screen_write_insert_lines(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_below_y(s, s->cy)); + + if (s->cy < s->rupper || s->cy > s->rlower) + screen_display_insert_lines(s, s->cy, n); + else + screen_display_insert_lines_region(s, s->cy, n); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_INSERTLINE, n); +} + +/* Insert characters. */ +void +screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 1, screen_right_x(s, s->cx)); + + screen_display_insert_characters(s, s->cx, s->cy, n); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_INSERTCHARACTER, n); +} + +/* Move the cursor. */ +void +screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m) +{ + struct screen *s = ctx->s; + + screen_write_limit(n, 0, screen_last_x(s)); + screen_write_limit(m, 0, screen_last_y(s)); + + s->cx = n; + s->cy = m; + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); +} + +/* Full to end of screen. */ +void +screen_write_fill_end_of_screen(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + u_int i; + + screen_fill_area(s, s->cx, s->cy, + screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); + screen_fill_area(s, 0, s->cy + 1, + screen_below_y(s, s->cy + 1), 1, SCREEN_DEFDATA, s->attr, s->colr); + + if (ctx->write != NULL) { + ctx->write(ctx->data, TTY_CLEARENDOFLINE); + for (i = s->cy + 1; i < screen_size_y(s); i++) { + ctx->write(ctx->data, TTY_CURSORMOVE, i, 0); + ctx->write(ctx->data, TTY_CLEARENDOFLINE); + } + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); + } +} + +/* Fill entire screen. */ +void +screen_write_fill_screen(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + u_int i; + + screen_display_fill_area(s, 0, 0, screen_size_x(s), screen_size_y(s), + SCREEN_DEFDATA, s->attr, s->colr); + + if (ctx->write != NULL) { + for (i = 0; i < screen_size_y(s); i++) { + ctx->write(ctx->data, TTY_CURSORMOVE, i, 0); + ctx->write(ctx->data, TTY_CLEARENDOFLINE); + } + ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); + } +} + +/* Fill to end of line. */ +void +screen_write_fill_end_of_line(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + screen_display_fill_area(s, s->cx, s->cy, + screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARENDOFLINE); +} + +/* Fill to start of line. */ +void +screen_write_fill_start_of_line(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + screen_display_fill_area(s, 0, s->cy, + screen_left_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARSTARTOFLINE); +} + +/* Fill entire line. */ +void +screen_write_fill_line(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + + screen_display_fill_area(s, 0, s->cy, + screen_size_x(s), s->cy, SCREEN_DEFDATA, s->attr, s->colr); + + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARLINE); +} + +/* Set a screen mode. */ +void +screen_write_set_mode(struct screen_write_ctx *ctx, int mode) +{ + struct screen *s = ctx->s; + + s->mode |= mode; + + if (ctx->write == NULL) + return; + + if (mode & MODE_INSERT) + ctx->write(ctx->data, TTY_INSERTON); + if (mode & MODE_KCURSOR) + ctx->write(ctx->data, TTY_KCURSORON); + if (mode & MODE_KKEYPAD) + ctx->write(ctx->data, TTY_KKEYPADON); + if (mode & MODE_MOUSE) + ctx->write(ctx->data, TTY_MOUSEON); +} + +/* Clear a screen mode. */ +void +screen_write_clear_mode(struct screen_write_ctx *ctx, int mode) +{ + struct screen *s = ctx->s; + + s->mode &= ~mode; + + if (ctx->write == NULL) + return; + + if (mode & MODE_INSERT) + ctx->write(ctx->data, TTY_INSERTOFF); + if (mode & MODE_KCURSOR) + ctx->write(ctx->data, TTY_KCURSOROFF); + if (mode & MODE_KKEYPAD) + ctx->write(ctx->data, TTY_KKEYPADOFF); + if (mode & MODE_MOUSE) + ctx->write(ctx->data, TTY_MOUSEOFF); +} + +/* Copy cells from another screen. */ +void +screen_write_copy_area(struct screen_write_ctx *ctx, + struct screen *src, u_int nx, u_int ny, u_int ox, u_int oy) +{ + struct screen *s = ctx->s; + struct screen_redraw_ctx rctx; + int saved_mode; + + screen_write_limit(nx, 1, screen_right_x(s, s->cx)); + screen_write_limit(ny, 1, screen_below_y(s, s->cy)); + + screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy); + + if (ctx->write != NULL) { + /* Save mode XXX hack */ + saved_mode = ctx->s->mode; + ctx->s->mode &= ~MODE_CURSOR; + + screen_redraw_start(&rctx, ctx->s, ctx->write, ctx->data); + screen_redraw_area(&rctx, s->cx, s->cy, nx, ny); + screen_redraw_stop(&rctx); + + ctx->s->mode = saved_mode; + } +} |