character_set saved_cs, saved_g0, saved_g1;
keyboard_mode key_mode;
int data_pitch, attr_pitch; /* The width in bytes of a line */
- int width, height, start, row, column;
+ int width, height, row, column, max_width;
+ uint32_t buffer_height;
+ uint32_t start, end, saved_start, log_size;
int saved_row, saved_column;
+ int scrolling;
int send_cursor_position;
int fd, master;
uint32_t modifiers;
{
int index;
- index = (row + terminal->start) % terminal->height;
+ index = (row + terminal->start) & (terminal->buffer_height - 1);
- return &terminal->data[index * terminal->width];
+ return (void *) terminal->data + index * terminal->data_pitch;
}
static struct attr*
{
int index;
- index = (row + terminal->start) % terminal->height;
+ index = (row + terminal->start) & (terminal->buffer_height - 1);
- return &terminal->data_attr[index * terminal->width];
+ return (void *) terminal->data_attr + index * terminal->attr_pitch;
}
union decoded_attr {
{
int i;
- d = d % (terminal->height + 1);
- terminal->start = (terminal->start + d) % terminal->height;
- if (terminal->start < 0) terminal->start = terminal->height + terminal->start;
- if(d < 0) {
+ terminal->start += d;
+ if (d < 0) {
d = 0 - d;
- for(i = 0; i < d; i++) {
+ for (i = 0; i < d; i++) {
memset(terminal_get_row(terminal, i), 0, terminal->data_pitch);
attr_init(terminal_get_attr_row(terminal, i),
terminal->curr_attr, terminal->width);
}
} else {
- for(i = terminal->height - d; i < terminal->height; i++) {
+ for (i = terminal->height - d; i < terminal->height; i++) {
memset(terminal_get_row(terminal, i), 0, terminal->data_pitch);
attr_init(terminal_get_attr_row(terminal, i),
terminal->curr_attr, terminal->width);
}
static void
-terminal_resize_cells(struct terminal *terminal, int width, int height)
+terminal_resize_cells(struct terminal *terminal,
+ int width, int height)
{
- size_t size;
union utf8_char *data;
struct attr *data_attr;
char *tab_ruler;
int data_pitch, attr_pitch;
int i, l, total_rows;
+ uint32_t d, uheight = height;
struct rectangle allocation;
struct winsize ws;
+ if (uheight > terminal->buffer_height)
+ height = terminal->buffer_height;
+
if (terminal->width == width && terminal->height == height)
return;
- data_pitch = width * sizeof(union utf8_char);
- size = data_pitch * height;
- data = zalloc(size);
- attr_pitch = width * sizeof(struct attr);
- data_attr = malloc(attr_pitch * height);
- tab_ruler = zalloc(width);
- attr_init(data_attr, terminal->curr_attr, width * height);
- if (terminal->data && terminal->data_attr) {
- if (width > terminal->width)
- l = terminal->width;
- else
- l = width;
-
- if (terminal->height > height) {
- total_rows = height;
- i = 1 + terminal->row - height;
- if (i > 0) {
- terminal->start = (terminal->start + i) % terminal->height;
- terminal->row = terminal->row - i;
- }
- } else {
- total_rows = terminal->height;
+ if (terminal->data && width <= terminal->max_width) {
+ d = 0;
+ if (height < terminal->height && height <= terminal->row)
+ d = terminal->height - height;
+ else if (height > terminal->height &&
+ terminal->height - 1 == terminal->row) {
+ d = terminal->height - height;
+ if (terminal->log_size < uheight)
+ d = -terminal->start;
}
- for (i = 0; i < total_rows; i++) {
- memcpy(&data[width * i],
- terminal_get_row(terminal, i),
- l * sizeof(union utf8_char));
- memcpy(&data_attr[width * i],
- terminal_get_attr_row(terminal, i),
- l * sizeof(struct attr));
+ terminal->start += d;
+ terminal->row -= d;
+ } else {
+ terminal->max_width = width;
+ data_pitch = width * sizeof(union utf8_char);
+ data = zalloc(data_pitch * terminal->buffer_height);
+ attr_pitch = width * sizeof(struct attr);
+ data_attr = malloc(attr_pitch * terminal->buffer_height);
+ tab_ruler = zalloc(width);
+ attr_init(data_attr, terminal->curr_attr,
+ width * terminal->buffer_height);
+
+ if (terminal->data && terminal->data_attr) {
+ if (width > terminal->width)
+ l = terminal->width;
+ else
+ l = width;
+
+ if (terminal->height > height) {
+ total_rows = height;
+ i = 1 + terminal->row - height;
+ if (i > 0) {
+ terminal->start += i;
+ terminal->row = terminal->row - i;
+ }
+ } else {
+ total_rows = terminal->height;
+ }
+
+ for (i = 0; i < total_rows; i++) {
+ memcpy(&data[width * i],
+ terminal_get_row(terminal, i),
+ l * sizeof(union utf8_char));
+ memcpy(&data_attr[width * i],
+ terminal_get_attr_row(terminal, i),
+ l * sizeof(struct attr));
+ }
+
+ free(terminal->data);
+ free(terminal->data_attr);
+ free(terminal->tab_ruler);
}
- free(terminal->data);
- free(terminal->data_attr);
- free(terminal->tab_ruler);
+ terminal->data_pitch = data_pitch;
+ terminal->attr_pitch = attr_pitch;
+ terminal->data = data;
+ terminal->data_attr = data_attr;
+ terminal->tab_ruler = tab_ruler;
+ terminal_init_tabs(terminal);
+ terminal->start = 0;
}
- terminal->data_pitch = data_pitch;
- terminal->attr_pitch = attr_pitch;
terminal->margin_bottom =
height - (terminal->height - terminal->margin_bottom);
terminal->width = width;
terminal->height = height;
- terminal->data = data;
- terminal->data_attr = data_attr;
- terminal->tab_ruler = tab_ruler;
- terminal->start = 0;
- terminal_init_tabs(terminal);
/* Update the window size */
ws.ws_row = terminal->height;
terminal->curr_attr, terminal->width);
}
} else if (args[0] == 2) {
- for (i = 0; i < terminal->height; i++) {
- memset(terminal_get_row(terminal, i),
- 0, terminal->data_pitch);
- attr_init(terminal_get_attr_row(terminal, i),
- terminal->curr_attr, terminal->width);
- }
+ /* Clear screen by scrolling contents out */
+ terminal_scroll_buffer(terminal,
+ terminal->end - terminal->start);
}
break;
case 'K': /* EL */
case '\v':
case '\f':
terminal->row++;
- if(terminal->row > terminal->margin_bottom) {
+ if (terminal->row + terminal->start > terminal->end)
+ terminal->end = terminal->row + terminal->start;
+ if (terminal->end == terminal->buffer_height)
+ terminal->log_size = terminal->buffer_height;
+ else if (terminal->log_size < terminal->buffer_height)
+ terminal->log_size = terminal->end;
+
+ if (terminal->row > terminal->margin_bottom) {
terminal->row = terminal->margin_bottom;
terminal_scroll(terminal, +1);
}
return 1;
+ case XKB_KEY_Up:
+ if (!terminal->scrolling)
+ terminal->saved_start = terminal->start;
+ if (terminal->start == terminal->end - terminal->log_size)
+ return 1;
+
+ terminal->scrolling = 1;
+ terminal->start--;
+ terminal->row++;
+ terminal->selection_start_row++;
+ terminal->selection_end_row++;
+ widget_schedule_redraw(terminal->widget);
+ return 1;
+
+ case XKB_KEY_Down:
+ if (!terminal->scrolling)
+ terminal->saved_start = terminal->start;
+
+ if (terminal->start == terminal->saved_start)
+ return 1;
+
+ terminal->scrolling = 1;
+ terminal->start++;
+ terminal->row--;
+ terminal->selection_start_row--;
+ terminal->selection_end_row--;
+ widget_schedule_redraw(terminal->widget);
+ return 1;
+
default:
return 0;
}
struct terminal *terminal = data;
char ch[MAX_RESPONSE];
uint32_t modifiers, serial;
- int ret, len = 0;
+ int ret, len = 0, d;
bool convert_utf8 = true;
modifiers = input_get_modifiers(input);
}
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && len > 0) {
+ if (terminal->scrolling) {
+ d = terminal->saved_start - terminal->start;
+ terminal->row -= d;
+ terminal->selection_start_row -= d;
+ terminal->selection_end_row -= d;
+ terminal->start = terminal->saved_start;
+ terminal->scrolling = 0;
+ widget_schedule_redraw(terminal->widget);
+ }
+
terminal_write(terminal, ch, len);
/* Hide cursor, except if this was coming from a
terminal->display = display;
terminal->margin = 5;
+ terminal->buffer_height = 1024;
+ terminal->end = 1;
window_set_user_data(terminal->window, terminal);
window_set_key_handler(terminal->window, key_handler);