aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-05-04 20:41:40 -0400
committerJesse Luehrs <doy@tozt.net>2014-05-04 20:41:40 -0400
commit2cad542ca939cd42a30f3d0b75f97a14095e3da5 (patch)
tree2dea84f07acfca1c014bc3142748016c30f61e67
parente9ff48e51a9df78375ce703ff3d4df1a362ac259 (diff)
downloadrunes-2cad542ca939cd42a30f3d0b75f97a14095e3da5.tar.gz
runes-2cad542ca939cd42a30f3d0b75f97a14095e3da5.zip
cap scrollback to avoid unbounded memory usage
-rw-r--r--src/config.c4
-rw-r--r--src/config.h1
-rw-r--r--src/screen.c34
3 files changed, 33 insertions, 6 deletions
diff --git a/src/config.c b/src/config.c
index 3a4ae4a..689f042 100644
--- a/src/config.c
+++ b/src/config.c
@@ -312,6 +312,7 @@ static void runes_config_set_defaults(RunesTerm *t)
config->default_cols = 80;
config->scroll_lines = 3;
+ config->scrollback_length = 4096;
}
static FILE *runes_config_get_config_file()
@@ -499,6 +500,9 @@ static void runes_config_set(RunesTerm *t, char *key, char *val)
else if (!strcmp(key, "scroll_lines")) {
config->scroll_lines = runes_config_parse_uint(val);
}
+ else if (!strcmp(key, "scrollback_length")) {
+ config->scrollback_length = runes_config_parse_uint(val);
+ }
else if (!strcmp(key, "command")) {
config->cmd = runes_config_parse_string(val);
}
diff --git a/src/config.h b/src/config.h
index a98d9d0..58b781b 100644
--- a/src/config.h
+++ b/src/config.h
@@ -13,6 +13,7 @@ struct runes_config {
int default_cols;
int scroll_lines;
+ int scrollback_length;
char *cmd;
char *font_name;
diff --git a/src/screen.c b/src/screen.c
index 3681eb4..86a29c0 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -810,13 +810,35 @@ static void runes_screen_scroll_down(RunesTerm *t, int count)
}
}
else {
- runes_screen_ensure_capacity(t, scr->grid->row_count + count);
- for (i = 0; i < count; ++i) {
- row = runes_screen_row_at(t, i + scr->grid->max.row);
- row->cells = calloc(scr->grid->max.col, sizeof(struct runes_cell));
+ int scrollback = t->config.scrollback_length;
+
+ if (scr->grid->row_count + count > scrollback) {
+ int overflow = scr->grid->row_count + count - scrollback;
+
+ runes_screen_ensure_capacity(t, scrollback);
+ for (i = 0; i < overflow; ++i) {
+ free(scr->grid->rows[i].cells);
+ }
+ memmove(
+ &scr->grid->rows[0], &scr->grid->rows[overflow],
+ (scrollback - overflow) * sizeof(struct runes_row));
+ for (i = scrollback - count; i < scrollback; ++i) {
+ scr->grid->rows[i].cells = calloc(
+ scr->grid->max.col, sizeof(struct runes_cell));
+ }
+ scr->grid->row_count = scrollback;
+ scr->grid->row_top = scrollback - scr->grid->max.row;
+ }
+ else {
+ runes_screen_ensure_capacity(t, scr->grid->row_count + count);
+ for (i = 0; i < count; ++i) {
+ row = runes_screen_row_at(t, i + scr->grid->max.row);
+ row->cells = calloc(
+ scr->grid->max.col, sizeof(struct runes_cell));
+ }
+ scr->grid->row_count += count;
+ scr->grid->row_top += count;
}
- scr->grid->row_count += count;
- scr->grid->row_top += count;
}
}