terminal: implement IL/DL in vga terminal; experiment with scrollable regions

This commit is contained in:
K. Lange 2019-12-19 13:45:20 +09:00
parent a6d9b7c320
commit 1abba60e76
4 changed files with 115 additions and 33 deletions

View File

@ -1,9 +1,9 @@
/**
* This is a baked, single-file version of bim.
* It was built Tue Dec 17 13:18:29 2019
* It is based on git commit 2f4da2036745c3f1b7d532988f346abcca0e59eb
* It was built Thu Dec 19 13:41:35 2019
* It is based on git commit 8860761a4e0906246a38f41939551fe7ed050c5b
*/
#define GIT_TAG "2f4da20-baked"
#define GIT_TAG "8860761-baked"
/* Bim - A Text Editor
*
* Copyright (C) 2012-2019 K. Lange
@ -197,6 +197,7 @@ typedef struct {
unsigned int can_24bit:1;
unsigned int can_256color:1;
unsigned int can_italic:1;
unsigned int can_insert:1;
unsigned int history_enabled:1;
unsigned int highlight_parens:1;
unsigned int smart_case:1;
@ -639,6 +640,7 @@ global_config_t global_config = {
.can_24bit = 1, /* can use 24-bit color */
.can_256color = 1, /* can use 265 colors */
.can_italic = 1, /* can use italics (without inverting) */
.can_insert = 0, /* ^[[L */
/* Configuration options */
.history_enabled = 1,
.highlight_parens = 1, /* highlight parens/braces when cursor moves */
@ -2396,6 +2398,16 @@ void shift_down(int amount) {
printf("\033[%dT", amount);
}
void insert_lines_at(int line, int count) {
place_cursor(1, line);
printf("\033[%dL", count);
}
void delete_lines_at(int line, int count) {
place_cursor(1, line);
printf("\033[%dM", count);
}
/**
* Switch to the alternate terminal screen.
*/
@ -4507,7 +4519,12 @@ BIM_ACTION(cursor_down, 0,
/* Tell terminal to scroll */
if (global_config.can_scroll && !left_buffer) {
shift_up(1);
if (!global_config.can_insert) {
shift_up(1);
redraw_tabbar();
} else {
delete_lines_at(global_config.tabs_visible ? 2 : 1, 1);
}
/* A new line appears on screen at the bottom, draw it */
int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
@ -4519,7 +4536,6 @@ BIM_ACTION(cursor_down, 0,
} else {
redraw_text();
}
redraw_tabbar();
redraw_statusbar();
redraw_commandline();
place_cursor_actual();
@ -4593,7 +4609,12 @@ BIM_ACTION(cursor_up, 0,
/* Tell terminal to scroll */
if (global_config.can_scroll && !left_buffer) {
shift_down(1);
if (!global_config.can_insert) {
shift_down(1);
redraw_tabbar();
} else {
insert_lines_at(global_config.tabs_visible ? 2 : 1, 1);
}
/*
* The line at the top of the screen should always be real
@ -4601,9 +4622,9 @@ BIM_ACTION(cursor_up, 0,
*/
redraw_line(env->offset);
} else {
redraw_tabbar();
redraw_text();
}
redraw_tabbar();
redraw_statusbar();
redraw_commandline();
place_cursor_actual();
@ -7058,14 +7079,19 @@ void handle_common_mouse(int buttons, int x, int y) {
env->loading = 0;
if (!shifted) return;
if (global_config.can_scroll && !left_buffer) {
shift_down(shifted);
if (!global_config.can_insert) {
shift_down(shifted);
redraw_tabbar();
} else {
insert_lines_at(global_config.tabs_visible ? 2 : 1, shifted);
}
for (int i = 0; i < shifted; ++i) {
redraw_line(env->offset+i);
}
} else {
redraw_tabbar();
redraw_text();
}
redraw_tabbar();
redraw_statusbar();
redraw_commandline();
place_cursor_actual();
@ -7093,7 +7119,12 @@ void handle_common_mouse(int buttons, int x, int y) {
env->loading = 0;
if (!shifted) return;
if (global_config.can_scroll && !left_buffer) {
shift_up(shifted);
if (!global_config.can_insert) {
shift_up(shifted);
redraw_tabbar();
} else {
delete_lines_at(global_config.tabs_visible ? 2 : 1, shifted);
}
int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
for (int i = 0; i < shifted; ++i) {
if (env->offset + l - i < env->line_count + 1) {
@ -7103,9 +7134,9 @@ void handle_common_mouse(int buttons, int x, int y) {
}
}
} else {
redraw_tabbar();
redraw_text();
}
redraw_tabbar();
redraw_statusbar();
redraw_commandline();
place_cursor_actual();
@ -10258,6 +10289,10 @@ void detect_weird_terminals(void) {
if (term && strstr(term,"toaru-vga") == term) {
global_config.can_24bit = 0; /* Also not strictly true */
global_config.can_256color = 0; /* Not strictly true */
global_config.can_insert = 1;
}
if (term && strstr(term,"xterm-256color") == term) {
global_config.can_insert = 1;
}
if (!global_config.can_unicode) {

View File

@ -503,32 +503,57 @@ void term_redraw_all() {
}
}
void term_scroll(int how_much) {
if (how_much >= term_height || -how_much >= term_height) {
term_clear();
return;
void term_shift_region(int top, int height, int how_much) {
if (how_much == 0) return;
void * destination, * source;
int count, new_top, new_bottom;
if (how_much > height) {
count = 0;
new_top = top;
new_bottom = top + height;
} else if (how_much > 0) {
destination = term_buffer + term_width * top;
source = term_buffer + term_width * (top + how_much);
count = height - how_much;
new_top = top + height - how_much;
new_bottom = top + height;
} else if (how_much < 0) {
destination = term_buffer + term_width * (top - how_much);
source = term_buffer + term_width * top;
count = height + how_much;
new_top = top;
new_bottom = top - how_much;
}
if (how_much == 0) {
return;
/* Move from top+how_much to top */
if (count) {
memmove(destination, source, count * term_width * sizeof(term_cell_t));
}
if (how_much > 0) {
/* Shift terminal cells one row up */
memmove(term_buffer, (void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * how_much), sizeof(term_cell_t) * term_width * (term_height - how_much));
/* Reset the "new" row to clean cells */
memset((void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * (term_height - how_much)), 0x0, sizeof(term_cell_t) * term_width * how_much);
for (int i = 0; i < how_much; ++i) {
for (uint16_t x = 0; x < term_width; ++x) {
cell_set(x,term_height - how_much,' ', current_fg, current_bg, ansi_state->flags);
}
/* Clear new lines at bottom */
for (int i = new_top; i < new_bottom; ++i) {
for (uint16_t x = 0; x < term_width; ++x) {
cell_set(x, i, ' ', current_fg, current_bg, ansi_state->flags);
}
term_redraw_all();
}
term_redraw_all();
}
void term_scroll(int how_much) {
term_shift_region(0,term_height,how_much);
}
void insert_delete_lines(int how_many) {
if (how_many == 0) return;
if (how_many > 0) {
/* Insert lines is equivalent to scrolling from the current line */
term_shift_region(csr_y,term_height-csr_y,-how_many);
} else {
how_much = -how_much;
/* Shift terminal cells one row up */
memmove((void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * how_much), term_buffer, sizeof(term_cell_t) * term_width * (term_height - how_much));
/* Reset the "new" row to clean cells */
memset(term_buffer, 0x0, sizeof(term_cell_t) * term_width * how_much);
term_redraw_all();
term_shift_region(csr_y,term_height-csr_y,-how_many);
}
}
@ -910,6 +935,7 @@ term_callbacks_t term_callbacks = {
unsupported_int,
term_set_csr_show,
term_switch_buffer,
insert_delete_lines,
};
void reinit(void) {

View File

@ -37,6 +37,7 @@ typedef struct {
int (*get_cell_height)(void);
void (*set_csr_on)(int);
void (*switch_buffer)(int);
void (*insert_delete_lines)(int);
} term_callbacks_t;
typedef struct {
@ -90,6 +91,8 @@ typedef struct {
#define ANSI_RCP 'u' /* Restore Cursor Position */
#define ANSI_HIDE 'l' /* DECTCEM - Hide Cursor */
#define ANSI_SHOW 'h' /* DECTCEM - Show Cursor */
#define ANSI_IL 'L' /* Insert Line(s) */
#define ANSI_DL 'M' /* Delete Line(s) */
/* Display flags */
#define ANSI_BOLD 0x01
#define ANSI_UNDERLINE 0x02

View File

@ -450,6 +450,24 @@ static void _ansi_put(term_state_t * s, char c) {
callbacks->scroll(-how_many);
}
break;
case ANSI_IL:
{
int how_many = 1;
if (argc > 0) {
how_many = atoi(argv[0]);
}
callbacks->insert_delete_lines(how_many);
}
break;
case ANSI_DL:
{
int how_many = 1;
if (argc > 0) {
how_many = atoi(argv[0]);
}
callbacks->insert_delete_lines(-how_many);
}
break;
case 'X':
{
int how_many = 1;