mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Cut memory consumption by only allocating lines when there is actually data on them, and only as much as the right-most data. Everything else is filled in at runtime.
This commit is contained in:
		
							
								
								
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							@@ -1,5 +1,7 @@
 | 
			
		||||
21 November 2007
 | 
			
		||||
 | 
			
		||||
* Create every line as zero length and only expand it as data is written,
 | 
			
		||||
  rather than creating at full size immediately.
 | 
			
		||||
* Make command output (eg list-keys) go to a scrollable window similar to
 | 
			
		||||
  scroll mode.
 | 
			
		||||
* Redo screen redrawing so it is a) readable b) split into utility functions
 | 
			
		||||
@@ -247,4 +249,4 @@
 | 
			
		||||
  (including mutt, emacs). No status bar yet and no key remapping or other
 | 
			
		||||
  customisation.
 | 
			
		||||
 | 
			
		||||
$Id: CHANGES,v 1.79 2007-11-21 19:44:04 nicm Exp $
 | 
			
		||||
$Id: CHANGES,v 1.80 2007-11-21 22:20:44 nicm Exp $
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-list-windows.c,v 1.10 2007-11-21 13:11:41 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-list-windows.c,v 1.11 2007-11-21 22:20:44 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -42,15 +42,28 @@ const struct cmd_entry cmd_list_windows_entry = {
 | 
			
		||||
void
 | 
			
		||||
cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	u_int			 i, sy;
 | 
			
		||||
	unsigned long long	 size;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(wl, winlinks, &ctx->session->windows) {
 | 
			
		||||
		w = wl->window;
 | 
			
		||||
		ctx->print(ctx, "%d: %s \"%s\" (%s) [%ux%u] [history %u]",
 | 
			
		||||
 | 
			
		||||
		sy = w->screen.hsize + w->screen.dy;
 | 
			
		||||
		size = sizeof *w;
 | 
			
		||||
		for (i = 0; i < sy; i++)
 | 
			
		||||
			size += 4 + w->screen.grid_size[i] * 3;
 | 
			
		||||
		size += sy * (sizeof *w->screen.grid_data);
 | 
			
		||||
		size += sy * (sizeof *w->screen.grid_attr);
 | 
			
		||||
		size += sy * (sizeof *w->screen.grid_colr);
 | 
			
		||||
		size += sy * (sizeof *w->screen.grid_size);
 | 
			
		||||
 | 
			
		||||
		ctx->print(ctx,
 | 
			
		||||
		    "%d: %s \"%s\" (%s) [%ux%u] [history %u] [%llu bytes]",
 | 
			
		||||
		    wl->idx, w->name, w->screen.title, ttyname(w->fd),
 | 
			
		||||
		    screen_size_x(&w->screen), screen_size_y(&w->screen),
 | 
			
		||||
		    w->screen.hsize);
 | 
			
		||||
		    w->screen.hsize, size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ctx->cmdclient != NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: screen-display.c,v 1.4 2007-11-21 21:28:58 nicm Exp $ */
 | 
			
		||||
/* $Id: screen-display.c,v 1.5 2007-11-21 22:20:44 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -139,9 +139,7 @@ screen_display_cursor_set(struct screen *s, u_char ch)
 | 
			
		||||
	px = screen_x(s, s->cx);
 | 
			
		||||
	py = screen_y(s, s->cy);
 | 
			
		||||
 | 
			
		||||
	s->grid_data[py][px] = ch;
 | 
			
		||||
	s->grid_attr[py][px] = s->attr;
 | 
			
		||||
	s->grid_colr[py][px] = s->colr;
 | 
			
		||||
	screen_set_cell(s, px, py, ch, s->attr, s->colr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor up and scroll if necessary. */
 | 
			
		||||
@@ -405,11 +403,15 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx)
 | 
			
		||||
 | 
			
		||||
	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.
 | 
			
		||||
	 * - Clear the range at px to px + nx.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (px + nx != screen_last_x(s)) {
 | 
			
		||||
@@ -418,6 +420,7 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx)
 | 
			
		||||
		memmove(&s->grid_attr[py][px + nx], &s->grid_attr[py][px], mx);
 | 
			
		||||
		memmove(&s->grid_colr[py][px + nx], &s->grid_colr[py][px], mx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&s->grid_data[py][px], SCREEN_DEFDATA, nx);
 | 
			
		||||
	memset(&s->grid_attr[py][px], SCREEN_DEFATTR, nx);
 | 
			
		||||
	memset(&s->grid_colr[py][px], SCREEN_DEFCOLR, nx);
 | 
			
		||||
@@ -437,11 +440,15 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx)
 | 
			
		||||
 | 
			
		||||
	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 the last x - (rx - lx)  to the last x.
 | 
			
		||||
	 * - Clear the range from sx - nx to sx.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (px + nx != screen_last_x(s)) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										137
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								screen.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: screen.c,v 1.34 2007-11-21 21:28:58 nicm Exp $ */
 | 
			
		||||
/* $Id: screen.c,v 1.35 2007-11-21 22:20:44 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -110,7 +110,7 @@ screen_create(struct screen *s, u_int dx, u_int dy)
 | 
			
		||||
void
 | 
			
		||||
screen_resize(struct screen *s, u_int sx, u_int sy)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i, ox, oy, ny, my;
 | 
			
		||||
	u_int	ox, oy, ny, my;
 | 
			
		||||
 | 
			
		||||
	if (sx < 1)
 | 
			
		||||
		sx = 1;
 | 
			
		||||
@@ -126,23 +126,6 @@ screen_resize(struct screen *s, u_int sx, u_int sy)
 | 
			
		||||
	 * X dimension.
 | 
			
		||||
	 */
 | 
			
		||||
	if (sx != ox) {
 | 
			
		||||
		/* Resize on-screen lines. */
 | 
			
		||||
		for (i = s->hsize; i < s->hsize + oy; i++) {
 | 
			
		||||
			if (sx > s->grid_size[i]) {
 | 
			
		||||
				s->grid_data[i] = 
 | 
			
		||||
				    xrealloc(s->grid_data[i], sx, 1);
 | 
			
		||||
				s->grid_attr[i] =
 | 
			
		||||
				    xrealloc(s->grid_attr[i], sx, 1);
 | 
			
		||||
				s->grid_colr[i] =
 | 
			
		||||
				    xrealloc(s->grid_colr[i], sx, 1);
 | 
			
		||||
				s->grid_size[i] = sx;
 | 
			
		||||
			}
 | 
			
		||||
			if (sx > ox) {
 | 
			
		||||
				screen_fill_cells(s, ox, i, sx - ox,
 | 
			
		||||
				    SCREEN_DEFDATA, SCREEN_DEFATTR,
 | 
			
		||||
				    SCREEN_DEFCOLR);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (s->cx >= sx)
 | 
			
		||||
			s->cx = sx - 1;
 | 
			
		||||
		s->dx = sx;
 | 
			
		||||
@@ -201,6 +184,56 @@ screen_resize(struct screen *s, u_int sx, u_int sy)
 | 
			
		||||
	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], 1, nx);
 | 
			
		||||
	memset(&s->grid_data[py][ox], SCREEN_DEFDATA, nx - ox);
 | 
			
		||||
	s->grid_attr[py] = xrealloc(s->grid_attr[py], 1, nx);
 | 
			
		||||
	memset(&s->grid_attr[py][ox], SCREEN_DEFATTR, nx - ox);
 | 
			
		||||
	s->grid_colr[py] = xrealloc(s->grid_colr[py], 1, nx);
 | 
			
		||||
	memset(&s->grid_colr[py][ox], SCREEN_DEFCOLR, nx - ox);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell. */
 | 
			
		||||
void
 | 
			
		||||
screen_get_cell(struct screen *s,
 | 
			
		||||
    u_int cx, u_int cy, u_char *data, u_char *attr, u_char *colr)
 | 
			
		||||
{
 | 
			
		||||
	if (cx >= s->grid_size[cy]) {
 | 
			
		||||
		*data = SCREEN_DEFDATA;
 | 
			
		||||
		*attr = SCREEN_DEFATTR;
 | 
			
		||||
		*colr = SCREEN_DEFCOLR;
 | 
			
		||||
	} else {
 | 
			
		||||
		*data = s->grid_data[cy][cx];
 | 
			
		||||
		*attr = s->grid_attr[cy][cx];
 | 
			
		||||
		*colr = s->grid_colr[cy][cx];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set a cell. */
 | 
			
		||||
void
 | 
			
		||||
screen_set_cell(struct screen *s,
 | 
			
		||||
    u_int cx, u_int cy, u_char data, u_char attr, u_char colr)
 | 
			
		||||
{
 | 
			
		||||
	if (cx >= s->grid_size[cy]) {
 | 
			
		||||
		if (data == SCREEN_DEFDATA &&
 | 
			
		||||
		    attr == SCREEN_DEFATTR && colr == SCREEN_DEFCOLR)
 | 
			
		||||
			return;
 | 
			
		||||
		screen_expand_line(s, cy, cx + 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s->grid_data[cy][cx] = data;
 | 
			
		||||
	s->grid_attr[cy][cx] = attr;
 | 
			
		||||
	s->grid_colr[cy][cx] = colr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Destroy a screen. */
 | 
			
		||||
void
 | 
			
		||||
screen_destroy(struct screen *s)
 | 
			
		||||
@@ -235,6 +268,20 @@ screen_draw_start(struct screen_draw_ctx *ctx,
 | 
			
		||||
		input_store_zero(b, CODE_CURSOROFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell data during drawing. */
 | 
			
		||||
void
 | 
			
		||||
screen_draw_get_cell(struct screen_draw_ctx *ctx,
 | 
			
		||||
    u_int px, u_int py, u_char *data, u_char *attr, u_char *colr)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	u_int		 cx, cy;
 | 
			
		||||
	
 | 
			
		||||
	cx = ctx->ox + px;
 | 
			
		||||
	cy = screen_y(s, py) - ctx->oy;
 | 
			
		||||
 | 
			
		||||
	screen_get_cell(s, cx, cy, data, attr, colr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Finalise drawing. */
 | 
			
		||||
void
 | 
			
		||||
screen_draw_stop(struct screen_draw_ctx *ctx)
 | 
			
		||||
@@ -254,28 +301,6 @@ screen_draw_stop(struct screen_draw_ctx *ctx)
 | 
			
		||||
		input_store_zero(b, CODE_CURSORON);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell data. */
 | 
			
		||||
void
 | 
			
		||||
screen_draw_get_cell(struct screen_draw_ctx *ctx,
 | 
			
		||||
    u_int px, u_int py, u_char *data, u_char *attr, u_char *colr)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	u_int		 cx, cy;
 | 
			
		||||
	
 | 
			
		||||
	cx = ctx->ox + px;
 | 
			
		||||
	cy = screen_y(s, py) - ctx->oy;
 | 
			
		||||
 | 
			
		||||
	if (cx >= s->grid_size[cy]) {
 | 
			
		||||
		*data = SCREEN_DEFDATA;
 | 
			
		||||
		*attr = SCREEN_DEFATTR;
 | 
			
		||||
		*colr = SCREEN_DEFCOLR;
 | 
			
		||||
	} else {
 | 
			
		||||
		*data = s->grid_data[cy][cx];
 | 
			
		||||
		*attr = s->grid_attr[cy][cx];
 | 
			
		||||
		*colr = s->grid_colr[cy][cx];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor. */
 | 
			
		||||
void
 | 
			
		||||
screen_draw_move(struct screen_draw_ctx *ctx, u_int px, u_int py)
 | 
			
		||||
@@ -372,16 +397,13 @@ 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] = xmalloc(s->dx);
 | 
			
		||||
		s->grid_attr[i] = xmalloc(s->dx);
 | 
			
		||||
		s->grid_colr[i] = xmalloc(s->dx);
 | 
			
		||||
		s->grid_size[i] = s->dx;
 | 
			
		||||
		s->grid_data[i] = NULL;
 | 
			
		||||
		s->grid_attr[i] = NULL;
 | 
			
		||||
		s->grid_colr[i] = NULL;
 | 
			
		||||
		s->grid_size[i] = 0;
 | 
			
		||||
	}
 | 
			
		||||
	screen_fill_lines(
 | 
			
		||||
	    s, py, ny, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Free a range of ny lines at py. */
 | 
			
		||||
void
 | 
			
		||||
screen_free_lines(struct screen *s, u_int py, u_int ny)
 | 
			
		||||
@@ -389,9 +411,15 @@ screen_free_lines(struct screen *s, u_int py, u_int ny)
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	for (i = py; i < py + ny; i++) {
 | 
			
		||||
		xfree(s->grid_data[i]);
 | 
			
		||||
		xfree(s->grid_attr[i]);
 | 
			
		||||
		xfree(s->grid_colr[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_colr[i] != NULL)
 | 
			
		||||
			xfree(s->grid_colr[i]);
 | 
			
		||||
		s->grid_colr[i] = NULL;
 | 
			
		||||
		s->grid_size[i] = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -426,7 +454,8 @@ void
 | 
			
		||||
screen_fill_cells(struct screen *s,
 | 
			
		||||
    u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr)
 | 
			
		||||
{
 | 
			
		||||
	memset(&s->grid_data[py][px], data, nx);
 | 
			
		||||
	memset(&s->grid_attr[py][px], attr, nx);
 | 
			
		||||
	memset(&s->grid_colr[py][px], colr, nx);
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	for (i = px; i < px + nx; i++)
 | 
			
		||||
		screen_set_cell(s, i, py, data, attr, colr);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.h,v 1.91 2007-11-21 20:04:37 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.h,v 1.92 2007-11-21 22:20:44 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -61,7 +61,7 @@ extern char    *__progname;
 | 
			
		||||
#define TTY_NAME_MAX 32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAXTITLELEN	192
 | 
			
		||||
#define MAXTITLELEN	128
 | 
			
		||||
 | 
			
		||||
/* Fatal errors. */
 | 
			
		||||
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
 | 
			
		||||
@@ -764,6 +764,10 @@ u_char	 screen_stringcolour(const char *);
 | 
			
		||||
void	 screen_create(struct screen *, u_int, u_int);
 | 
			
		||||
void	 screen_destroy(struct screen *);
 | 
			
		||||
void	 screen_resize(struct screen *, u_int, u_int);
 | 
			
		||||
void	 screen_expand_line(struct screen *, u_int, u_int);
 | 
			
		||||
void	 screen_get_cell(
 | 
			
		||||
    	     struct screen *, u_int, u_int, u_char *, u_char *, u_char *);
 | 
			
		||||
void	 screen_set_cell(struct screen *, u_int, u_int, u_char, u_char, u_char);
 | 
			
		||||
void	 screen_draw_start(struct screen_draw_ctx *,
 | 
			
		||||
    	     struct screen *, struct buffer *, u_int, u_int);
 | 
			
		||||
void	 screen_draw_stop(struct screen_draw_ctx *);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user