mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Internal screen data rewrite for better 256 colour/UTF-8 support.
This commit is contained in:
		
							
								
								
									
										12
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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 $
 | 
			
		||||
 
 | 
			
		||||
@@ -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-
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								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 \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										125
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										199
									
								
								grid-view.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								grid-view.c
									
									
									
									
									
										Normal file
									
								
							@@ -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));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										353
									
								
								grid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								grid.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										358
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										358
									
								
								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;
 | 
			
		||||
 | 
			
		||||
	w->ictx.string_len = 0;
 | 
			
		||||
	w->ictx.string_buf = NULL;
 | 
			
		||||
	ARRAY_INIT(&ictx->args);
 | 
			
		||||
 | 
			
		||||
	input_state(&w->ictx, input_state_first);
 | 
			
		||||
	ictx->string_len = 0;
 | 
			
		||||
	ictx->string_buf = NULL;
 | 
			
		||||
 | 
			
		||||
 	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;
 | 
			
		||||
	struct grid_cell       *gc = &ictx->cell;
 | 
			
		||||
	u_int			i;
 | 
			
		||||
	uint16_t		m, o;
 | 
			
		||||
 | 
			
		||||
	attr = s->attr;
 | 
			
		||||
	fg = s->fg;
 | 
			
		||||
	bg = s->bg;
 | 
			
		||||
	if (ARRAY_LENGTH(&ictx->args) == 0) {
 | 
			
		||||
		memcpy(gc, &grid_default_cell, sizeof *gc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	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 (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 (o != 5)
 | 
			
		||||
				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;
 | 
			
		||||
			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:
 | 
			
		||||
			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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								log.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										477
									
								
								screen-display.c
									
									
									
									
									
								
							
							
						
						
									
										477
									
								
								screen-display.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								screen-redraw.c
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								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);
 | 
			
		||||
 | 
			
		||||
	ctx->s->cx++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Redraw area of cells. */
 | 
			
		||||
void
 | 
			
		||||
screen_redraw_area(
 | 
			
		||||
    struct screen_redraw_ctx *ctx, u_int px, u_int py, u_int nx, 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);
 | 
			
		||||
	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++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
	u_int	i, j;
 | 
			
		||||
 | 
			
		||||
	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 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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										837
									
								
								screen-write.c
									
									
									
									
									
								
							
							
						
						
									
										837
									
								
								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,227 +60,294 @@ 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;
 | 
			
		||||
	va_list	ap;
 | 
			
		||||
	char   *msg, *ptr;
 | 
			
		||||
 | 
			
		||||
	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_start(ap, fmt);
 | 
			
		||||
	xvasprintf(&msg, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
 | 
			
		||||
	s->cx++;
 | 
			
		||||
	for (ptr = msg; *ptr != '\0'; ptr++)
 | 
			
		||||
		screen_write_putc(ctx, gc, (u_char) *ptr);
 | 
			
		||||
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CHARACTER, ch);
 | 
			
		||||
	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;
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid_data	*gd = src->grid;
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	u_int		 	 xx, yy, cx, cy;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	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, ...)
 | 
			
		||||
{
 | 
			
		||||
	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. */
 | 
			
		||||
/* Cursor up by ny. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_set_attributes(
 | 
			
		||||
    struct screen_write_ctx *ctx, u_short attr, u_char fg, u_char bg)
 | 
			
		||||
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
{
 | 
			
		||||
	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 (ny > s->cy)
 | 
			
		||||
		ny = s->cy;
 | 
			
		||||
	if (ny == 0)
 | 
			
		||||
		ny = 1;
 | 
			
		||||
 | 
			
		||||
		if (ctx->write != NULL)
 | 
			
		||||
			ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
 | 
			
		||||
	}
 | 
			
		||||
	s->cy -= ny;
 | 
			
		||||
 | 
			
		||||
	if (ctx != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORUP, ny);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set scroll region.  */
 | 
			
		||||
/* Cursor down by ny. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower)
 | 
			
		||||
screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
	if (ny > screen_size_y(s) - 1 - s->cy)
 | 
			
		||||
		ny = screen_size_y(s) - 1 - s->cy;
 | 
			
		||||
	if (ny == 0)
 | 
			
		||||
		ny = 1;
 | 
			
		||||
	
 | 
			
		||||
	/* Cursor moves to top-left. */
 | 
			
		||||
	s->cx = 0;
 | 
			
		||||
	s->cy = upper;
 | 
			
		||||
 | 
			
		||||
	s->rupper = upper;
 | 
			
		||||
	s->rlower = lower;
 | 
			
		||||
	s->cy += ny;
 | 
			
		||||
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORDOWN, ny);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor up and scroll if necessary. */
 | 
			
		||||
/* Cursor right by nx.  */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cursor_up_scroll(struct screen_write_ctx *ctx)
 | 
			
		||||
screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
 | 
			
		||||
	if (nx > screen_size_x(s) - 1 - s->cx)
 | 
			
		||||
		nx = screen_size_x(s) - 1 - s->cx;
 | 
			
		||||
	if (nx == 0)
 | 
			
		||||
		nx = 1;
 | 
			
		||||
 | 
			
		||||
	s->cx += nx;
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORRIGHT, nx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Cursor left by nx. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	if (nx > s->cx)
 | 
			
		||||
		nx = s->cx;
 | 
			
		||||
	if (nx == 0)
 | 
			
		||||
		nx = 1;
 | 
			
		||||
 | 
			
		||||
	s->cx -= nx;
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORLEFT, nx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Insert nx characters. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	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_INSERTCHARACTER, nx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Delete nx characters. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Insert ny lines. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
 | 
			
		||||
	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_INSERTLINE, ny);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Delete ny lines. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
 | 
			
		||||
	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_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_DELETELINE, ny);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear line at cursor. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_clearline(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CLEARLINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to end of line from cursor. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_clearendofline(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	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_CLEARENDOFLINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to start of line from cursor. */
 | 
			
		||||
void
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
		s->mode &= ~MODE_CURSOR;
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORMODE, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Reverse index (up with scroll).  */
 | 
			
		||||
void
 | 
			
		||||
screen_write_reverseindex(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	if (s->cy == s->rupper)
 | 
			
		||||
		screen_display_scroll_region_down(s);
 | 
			
		||||
		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
 | 
			
		||||
	else if (s->cy > 0)
 | 
			
		||||
		s->cy--;
 | 
			
		||||
	
 | 
			
		||||
@@ -299,292 +355,263 @@ screen_write_cursor_up_scroll(struct screen_write_ctx *ctx)
 | 
			
		||||
		ctx->write(ctx->data, TTY_REVERSEINDEX);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor down and scroll if necessary  */
 | 
			
		||||
/* Set scroll region. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cursor_down_scroll(struct screen_write_ctx *ctx)
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	/* 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_SCROLLREGION, rupper, rlower);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set insert mode. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_insertmode(struct screen_write_ctx *ctx, int state)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	if (state)
 | 
			
		||||
		s->mode |= MODE_INSERT;
 | 
			
		||||
	else
 | 
			
		||||
		s->mode &= ~MODE_INSERT;
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_INSERTMODE, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set mouse mode.  */
 | 
			
		||||
void
 | 
			
		||||
screen_write_mousemode(struct screen_write_ctx *ctx, int state)
 | 
			
		||||
{
 | 
			
		||||
	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_MOUSEMODE, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Line feed (down with scroll). */
 | 
			
		||||
void
 | 
			
		||||
screen_write_linefeed(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))
 | 
			
		||||
		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)	/* XXX FORWARDINDEX */
 | 
			
		||||
		ctx->write(ctx->data, TTY_CHARACTER, '\n');
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_LINEFEED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor up. */
 | 
			
		||||
/* Carriage return (cursor to start of line). */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n)
 | 
			
		||||
screen_write_carriagereturn(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	screen_write_limit(s, n, 1, screen_above_y(s, s->cy) - 1);
 | 
			
		||||
 | 
			
		||||
	s->cy -= n;
 | 
			
		||||
	s->cx = 0;
 | 
			
		||||
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
 | 
			
		||||
		ctx->write(ctx->data, TTY_CARRIAGERETURN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor down. */
 | 
			
		||||
/* Set keypad cursor keys mode. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n)
 | 
			
		||||
screen_write_kcursormode(struct screen_write_ctx *ctx, int state)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	
 | 
			
		||||
	screen_write_limit(s, 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(s, 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(s, 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(s, 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);
 | 
			
		||||
	if (state)
 | 
			
		||||
		s->mode |= MODE_KCURSOR;
 | 
			
		||||
	else
 | 
			
		||||
		screen_display_delete_lines_region(s, s->cy, n);
 | 
			
		||||
		s->mode &= ~MODE_KCURSOR;
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_DELETELINE, n);
 | 
			
		||||
		ctx->write(ctx->data, TTY_KCURSORMODE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Delete characters. */
 | 
			
		||||
/* Set keypad number keys mode. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n)
 | 
			
		||||
screen_write_kkeypadmode(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_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(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_KKEYPAD;
 | 
			
		||||
	else
 | 
			
		||||
		screen_display_insert_lines_region(s, s->cy, n);
 | 
			
		||||
		s->mode &= ~MODE_KKEYPAD;	
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->write != NULL)
 | 
			
		||||
		ctx->write(ctx->data, TTY_INSERTLINE, n);
 | 
			
		||||
		ctx->write(ctx->data, TTY_KKEYPADMODE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Insert characters. */
 | 
			
		||||
/* Clear to end of screen from cursor. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n)
 | 
			
		||||
screen_write_clearendofscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
 	struct screen	*s = ctx->s;
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	u_int		 sx, sy;
 | 
			
		||||
 | 
			
		||||
	screen_write_limit(s, n, 1, screen_right_x(s, s->cx));
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
	sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	screen_display_insert_characters(s, s->cx, s->cy, n);
 | 
			
		||||
	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_INSERTCHARACTER, n);
 | 
			
		||||
		ctx->write(ctx->data, TTY_CLEARENDOFSCREEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move the cursor. */
 | 
			
		||||
/* Clear to start of screen. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m)
 | 
			
		||||
screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
 	struct screen	*s = ctx->s;
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	u_int		 sx, sy;
 | 
			
		||||
 | 
			
		||||
	screen_write_limit(s, n, 0, screen_last_x(s));
 | 
			
		||||
	screen_write_limit(s, m, 0, screen_last_y(s));
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
	sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	s->cx = n;
 | 
			
		||||
	s->cy = m;
 | 
			
		||||
	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_CURSORMOVE, s->cy, s->cx);
 | 
			
		||||
		ctx->write(ctx->data, TTY_CLEARSTARTOFSCREEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Full to end of screen. */
 | 
			
		||||
/* Clear entire screen. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_fill_end_of_screen(struct screen_write_ctx *ctx)
 | 
			
		||||
screen_write_clearscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
 	struct screen	*s = ctx->s;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
	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);
 | 
			
		||||
	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);
 | 
			
		||||
	grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
 | 
			
		||||
	
 | 
			
		||||
	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_CLEARSCREEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write cell data. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	width = utf8_width(gc->data);
 | 
			
		||||
 | 
			
		||||
	/* 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 = '_';
 | 
			
		||||
 | 
			
		||||
		width = 1;
 | 
			
		||||
		gc = &tc;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
/* 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), ' ', 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);
 | 
			
		||||
	/* 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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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, ' ', s->attr, s->fg, s->bg);
 | 
			
		||||
 | 
			
		||||
	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, ' ', s->attr, s->fg, s->bg);
 | 
			
		||||
 | 
			
		||||
	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, ' ', s->attr, s->fg, s->bg);
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	/* Sanity checks. */
 | 
			
		||||
	if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (mode & MODE_INSERT)
 | 
			
		||||
		ctx->write(ctx->data, TTY_INSERTON);
 | 
			
		||||
	if (mode & MODE_MOUSE)
 | 
			
		||||
		ctx->write(ctx->data, TTY_MOUSEON);
 | 
			
		||||
}
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
/* Clear a screen mode. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_clear_mode(struct screen_write_ctx *ctx, int mode)
 | 
			
		||||
{
 | 
			
		||||
 	struct screen	*s = ctx->s;
 | 
			
		||||
		/* Overwrite the character at the start of this padding. */
 | 
			
		||||
		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
 | 
			
		||||
 | 
			
		||||
	s->mode &= ~mode;
 | 
			
		||||
		/* 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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ctx->write == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mode & MODE_INSERT)
 | 
			
		||||
		ctx->write(ctx->data, TTY_INSERTOFF);
 | 
			
		||||
	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(s, nx, 1, screen_right_x(s, s->cx));
 | 
			
		||||
	screen_write_limit(s, ny, 1, screen_below_y(s, s->cy));
 | 
			
		||||
 | 
			
		||||
	screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy);
 | 
			
		||||
	/* Write the actual cell. */
 | 
			
		||||
	grid_view_set_cell(gd, s->cx, s->cy, gc);
 | 
			
		||||
	s->cx += width;
 | 
			
		||||
	
 | 
			
		||||
	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;
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										375
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										375
									
								
								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.
 | 
			
		||||
		 */
 | 
			
		||||
		if (sx < ox) {
 | 
			
		||||
			for (i = s->hsize; i < s->hsize + oy; i++) {
 | 
			
		||||
				if (s->grid_size[i] > sx)
 | 
			
		||||
					screen_reduce_line(s, i, sx);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (s->cx >= sx)
 | 
			
		||||
			s->cx = sx - 1;
 | 
			
		||||
		s->dx = sx;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Y dimension.
 | 
			
		||||
	 */
 | 
			
		||||
	if (sy == oy)
 | 
			
		||||
		return;
 | 
			
		||||
	/* 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 the character after the last is wide or padding, remove
 | 
			
		||||
		 * it and any leading padding.
 | 
			
		||||
		 */
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
		/* Reduce the line size. */
 | 
			
		||||
		grid_reduce_line(gd, yy, sx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gd->sy = sy;
 | 
			
		||||
		
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
	}
 | 
			
		||||
	s->rlower = screen_size_y(s) - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set selection. */
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								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,40 +186,39 @@ 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 (llen != 0)
 | 
			
		||||
			screen_redraw_move_cursor(&ctx, llen + 1, yy);
 | 
			
		||||
		if (larrow == -1)
 | 
			
		||||
			gc.attr |= GRID_ATTR_REVERSE;
 | 
			
		||||
		else
 | 
			
		||||
			screen_redraw_move_cursor(&ctx, 0, yy);
 | 
			
		||||
 		ctx.write(ctx.data, TTY_CHARACTER, '<');
 | 
			
		||||
			gc.attr &= ~GRID_ATTR_REVERSE;
 | 
			
		||||
		if (llen != 0)
 | 
			
		||||
			ctx.write(ctx.data, TTY_CURSORMOVE, llen + 1, yy);
 | 
			
		||||
		else
 | 
			
		||||
			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 (rlen != 0)
 | 
			
		||||
			screen_redraw_move_cursor(&ctx, c->sx - rlen - 2, yy);
 | 
			
		||||
		if (rarrow == -1)
 | 
			
		||||
			gc.attr |= GRID_ATTR_REVERSE;
 | 
			
		||||
		else
 | 
			
		||||
			screen_redraw_move_cursor(&ctx, c->sx - 1, yy);
 | 
			
		||||
 		ctx.write(ctx.data, TTY_CHARACTER, '>');
 | 
			
		||||
			gc.attr &= ~GRID_ATTR_REVERSE;
 | 
			
		||||
		if (rlen != 0)
 | 
			
		||||
			ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 2, yy);
 | 
			
		||||
		else
 | 
			
		||||
			ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - 1, yy);
 | 
			
		||||
		screen_redraw_putc(&ctx, &gc, '>');
 | 
			
		||||
		gc.attr &= ~GRID_ATTR_REVERSE;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	screen_redraw_stop(&ctx);
 | 
			
		||||
@@ -231,10 +227,9 @@ draw:
 | 
			
		||||
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;		
 | 
			
		||||
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
	screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	gc.attr |= GRID_ATTR_REVERSE;
 | 
			
		||||
 | 
			
		||||
	screen_redraw_move_cursor(&ctx, 0, yy);
 | 
			
		||||
	screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->message_string);
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
 | 
			
		||||
	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;		
 | 
			
		||||
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
	screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	gc.attr |= GRID_ATTR_REVERSE;
 | 
			
		||||
 | 
			
		||||
	screen_redraw_move_cursor(&ctx, 0, yy);
 | 
			
		||||
	screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->prompt_string);
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
 | 
			
		||||
	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. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										379
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										379
									
								
								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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										800
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										800
									
								
								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_cmds[cmd] != NULL)
 | 
			
		||||
		tty_cmds[cmd](tty, s, ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		if (tty->attr & ATTR_PAD)
 | 
			
		||||
			break;
 | 
			
		||||
void
 | 
			
		||||
tty_cmd_cursorup(struct tty *tty, unused struct screen *s, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
	u_int ua;
 | 
			
		||||
 | 
			
		||||
		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 = '_';
 | 
			
		||||
	ua = va_arg(ap, u_int);
 | 
			
		||||
 | 
			
		||||
		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 */
 | 
			
		||||
			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)
 | 
			
		||||
			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));
 | 
			
		||||
		}
 | 
			
		||||
		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++)
 | 
			
		||||
				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, 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));
 | 
			
		||||
		}
 | 
			
		||||
		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);
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
				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;
 | 
			
		||||
	if (parm_up_cursor != NULL)
 | 
			
		||||
		tty_puts(tty, tparm(parm_up_cursor, ua));
 | 
			
		||||
	else {
 | 
			
		||||
		while (ua-- > 0)
 | 
			
		||||
			tty_puts(tty, cursor_up);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_attributes(struct tty *tty, u_short attr, u_char fg, u_char bg)
 | 
			
		||||
tty_cmd_cursordown(struct tty *tty, unused struct screen *s, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
	if (attr == tty->attr && fg == tty->fg && bg == tty->bg)
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
	}
 | 
			
		||||
	ua = va_arg(ap, int);
 | 
			
		||||
	
 | 
			
		||||
	/* Filter out attribute bits already set. */
 | 
			
		||||
	attr &= ~tty->attr;
 | 
			
		||||
	tty->attr |= attr;
 | 
			
		||||
	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);
 | 
			
		||||
			tty_puts(tty, cursor_down);
 | 
			
		||||
		}
 | 
			
		||||
	} 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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, 0));
 | 
			
		||||
	} else {
 | 
			
		||||
		for (j = 0; j < s->cy; j++) {
 | 
			
		||||
			for (i = 0; i < screen_size_x(s); i++)
 | 
			
		||||
				tty_putc(tty, ' ');
 | 
			
		||||
		}		
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
		}
 | 
			
		||||
	} 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, tparm(cursor_address, s->cy, s->cx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_cmd_cell(struct tty *tty, unused struct screen *s, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	/* Handle special characters. Should never come into this function.*/
 | 
			
		||||
	if (gc->data < 0x20 || gc->data == 0x7f)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Set the attributes. */
 | 
			
		||||
	if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL)
 | 
			
		||||
	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. */
 | 
			
		||||
	changed = gc->attr & ~tc->attr;
 | 
			
		||||
	tc->attr = gc->attr;
 | 
			
		||||
 | 
			
		||||
	/* Set the attributes. */
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										139
									
								
								utf8.c
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								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)
 | 
			
		||||
u_int
 | 
			
		||||
utf8_combine(const u_char data[4])
 | 
			
		||||
{
 | 
			
		||||
	*data = idx & 0xff;
 | 
			
		||||
	u_int	uv;
 | 
			
		||||
 | 
			
		||||
	*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)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
utf8_free(struct utf8_table *utab)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	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_split(u_int uv, u_char data[4])
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										262
									
								
								window-copy.c
									
									
									
									
									
								
							
							
						
						
									
										262
									
								
								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;
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	u_int			 px;
 | 
			
		||||
 | 
			
		||||
	px = w->base.grid_size[py];
 | 
			
		||||
	while (px > 0 && w->base.grid_data[py][px - 1] == ' ')
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user