/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
static void screen_write_initctx(struct screen_write_ctx *,
struct tty_ctx *);
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
u_int);
static void screen_write_collect_scroll(struct screen_write_ctx *);
static void screen_write_collect_flush(struct screen_write_ctx *, int);
static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int);
static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
const struct utf8_data *, u_int *);
static const struct grid_cell screen_write_pad_cell = {
GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
};
struct screen_write_collect_item {
u_int x;
u_int used;
char data[256];
struct grid_cell gc;
TAILQ_ENTRY (screen_write_collect_item) entry;
};
struct screen_write_collect_line {
TAILQ_HEAD(, screen_write_collect_item) items;
};
/* Initialize writing with a window. */
void
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
struct screen *s)
{
char tmp[16];
u_int y;
memset(ctx, 0, sizeof *ctx);
ctx->wp = wp;
if (wp != NULL && s == NULL)
ctx->s = wp->screen;
else
ctx->s = s;
ctx->list = xcalloc(screen_size_y(ctx->s), sizeof *ctx->list);
for (y = 0; y < screen_size_y(ctx->s); y++)
TAILQ_INIT(&ctx->list[y].items);
ctx->item = xcalloc(1, sizeof *ctx->item);
if (wp != NULL)
snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
screen_size_y(ctx->s), wp == NULL ? "no pane" : tmp);
}
/* Finish writing. */
void
screen_write_stop(struct screen_write_ctx *ctx)
{
screen_write_collect_end(ctx);
screen_write_collect_flush(ctx, 0);
log_debug("%s: %u cells (%u written, %u skipped)", __func__,
ctx->cells, ctx->written, ctx->skipped);
free(ctx->item);
free(ctx->list); /* flush will have emptied */
}
/* Reset screen state. */
void
screen_write_reset(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
screen_reset_tabs(s);
screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1);
s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD|MODE_FOCUSON);
s->mode &= ~(ALL_MOUSE_MODES|MODE_MOUSE_UTF8|MODE_MOUSE_SGR);
screen_write_clearscreen(ctx, 8);
screen_write_cursormove(ctx, 0, 0);
}
/* Write character. */
void
screen_write_putc(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
u_char ch)
{
struct grid_cell gc;
memcpy(&
|