Attempt to fix scrolling in vim
Atleast now it can "emulate" scrolling
This commit is contained in:
parent
8bed0e9d52
commit
1ad881ba60
299
cowterm.c
299
cowterm.c
@ -1,3 +1,4 @@
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
@ -40,6 +41,8 @@ static Pixmap buffer_pixmap = None;
|
||||
static int master_fd = -1;
|
||||
static int needs_refresh = 0;
|
||||
static int window_focused = 0;
|
||||
static int scroll_top = 0; // 0 means entire terminal
|
||||
static int scroll_bottom = 0; // 0 means entire terminal
|
||||
|
||||
// Cursor stuff
|
||||
static int cursor_visible = 1;
|
||||
@ -435,6 +438,233 @@ static void scroll_up(void) {
|
||||
needs_refresh = 1;
|
||||
}
|
||||
|
||||
static void scroll_region_up(int amount) {
|
||||
char **temp_buffer = NULL;
|
||||
unsigned long **temp_color_buffer = NULL;
|
||||
int **temp_attr_buffer = NULL;
|
||||
unsigned long **temp_bg_color_buffer = NULL;
|
||||
|
||||
temp_buffer = malloc(term_rows * sizeof(char *));
|
||||
temp_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||
temp_attr_buffer = malloc(term_rows * sizeof(int *));
|
||||
temp_bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||
|
||||
if (!temp_buffer || !temp_color_buffer || !temp_attr_buffer ||
|
||||
!temp_bg_color_buffer) {
|
||||
fprintf(stderr, "Failed to allocate memory for temp buffers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
temp_buffer[i] = malloc(term_cols * sizeof(char));
|
||||
temp_color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||
temp_attr_buffer[i] = malloc(term_cols * sizeof(int));
|
||||
temp_bg_color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||
if (!temp_buffer[i] || !temp_color_buffer[i] || !temp_attr_buffer[i] ||
|
||||
!temp_bg_color_buffer[i]) {
|
||||
fprintf(stderr, "Failed to allocate memory for temp buffer row\n");
|
||||
free(temp_buffer);
|
||||
free(temp_color_buffer);
|
||||
free(temp_attr_buffer);
|
||||
free(temp_bg_color_buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (scroll_top == 0 && scroll_bottom == 0) {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
memcpy(temp_buffer[i], terminal_buffer[i], term_cols * sizeof(char));
|
||||
memcpy(temp_color_buffer[i], color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(temp_attr_buffer[i], attr_buffer[i], term_cols * sizeof(int));
|
||||
memcpy(temp_bg_color_buffer[i], bg_color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
for (int j = 0; j < amount; j++) {
|
||||
// Move all lines up one position
|
||||
for (int y = 0; y < term_rows - 1; y++) {
|
||||
memcpy(terminal_buffer[y], temp_buffer[y + 1], term_cols);
|
||||
memcpy(color_buffer[y], temp_color_buffer[y + 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(attr_buffer[y], temp_attr_buffer[y + 1],
|
||||
term_cols * sizeof(int));
|
||||
memcpy(bg_color_buffer[y], temp_bg_color_buffer[y + 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
// Clear the bottom line
|
||||
memset(terminal_buffer[term_rows - 1], ' ', term_cols);
|
||||
for (int x = 0; x < term_cols; x++) {
|
||||
color_buffer[term_rows - 1][x] = current_color;
|
||||
attr_buffer[term_rows - 1][x] = current_attr;
|
||||
bg_color_buffer[term_rows - 1][x] = current_bg_color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
memcpy(temp_buffer[i], terminal_buffer[i], term_cols * sizeof(char));
|
||||
memcpy(temp_color_buffer[i], color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(temp_attr_buffer[i], attr_buffer[i], term_cols * sizeof(int));
|
||||
memcpy(temp_bg_color_buffer[i], bg_color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
for (int j = 0; j < amount; j++) {
|
||||
int start = (scroll_top - 1);
|
||||
int end = (scroll_bottom - 1);
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
if (end >= term_rows)
|
||||
end = term_rows - 1;
|
||||
// Move all lines up one position
|
||||
for (int y = start; y < end; y++) {
|
||||
memcpy(terminal_buffer[y], temp_buffer[y + 1], term_cols);
|
||||
memcpy(color_buffer[y], temp_color_buffer[y + 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(attr_buffer[y], temp_attr_buffer[y + 1],
|
||||
term_cols * sizeof(int));
|
||||
memcpy(bg_color_buffer[y], temp_bg_color_buffer[y + 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
// Clear the bottom line
|
||||
memset(terminal_buffer[end], ' ', term_cols);
|
||||
for (int x = 0; x < term_cols; x++) {
|
||||
color_buffer[end][x] = current_color;
|
||||
attr_buffer[end][x] = current_attr;
|
||||
bg_color_buffer[end][x] = current_bg_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
free(temp_buffer[i]);
|
||||
free(temp_color_buffer[i]);
|
||||
free(temp_attr_buffer[i]);
|
||||
free(temp_bg_color_buffer[i]);
|
||||
}
|
||||
free(temp_buffer);
|
||||
free(temp_color_buffer);
|
||||
free(temp_attr_buffer);
|
||||
free(temp_bg_color_buffer);
|
||||
needs_refresh = 1;
|
||||
}
|
||||
|
||||
static void scroll_region_down(int amount) {
|
||||
char **temp_buffer = NULL;
|
||||
unsigned long **temp_color_buffer = NULL;
|
||||
int **temp_attr_buffer = NULL;
|
||||
unsigned long **temp_bg_color_buffer = NULL;
|
||||
|
||||
temp_buffer = malloc(term_rows * sizeof(char *));
|
||||
temp_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||
temp_attr_buffer = malloc(term_rows * sizeof(int *));
|
||||
temp_bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||
|
||||
if (!temp_buffer || !temp_color_buffer || !temp_attr_buffer ||
|
||||
!temp_bg_color_buffer) {
|
||||
fprintf(stderr, "Failed to allocate memory for temp buffers\n");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
temp_buffer[i] = malloc(term_cols * sizeof(char));
|
||||
temp_color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||
temp_attr_buffer[i] = malloc(term_cols * sizeof(int));
|
||||
temp_bg_color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||
|
||||
if (!temp_buffer[i] || !temp_color_buffer[i] || !temp_attr_buffer[i] ||
|
||||
!temp_bg_color_buffer[i]) {
|
||||
fprintf(stderr, "Failed to allocate memory for temp buffer row\n");
|
||||
free(temp_buffer);
|
||||
free(temp_color_buffer);
|
||||
free(temp_attr_buffer);
|
||||
free(temp_bg_color_buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (scroll_top == 0 && scroll_bottom == 0) {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
memcpy(temp_buffer[i], terminal_buffer[i], term_cols * sizeof(char));
|
||||
memcpy(temp_color_buffer[i], color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(temp_attr_buffer[i], attr_buffer[i], term_cols * sizeof(int));
|
||||
memcpy(temp_bg_color_buffer[i], bg_color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
for (int j = 0; j < amount; j++) {
|
||||
// Move all lines down one position
|
||||
for (int y = term_rows - 1; y > 0; y--) {
|
||||
memcpy(terminal_buffer[y], temp_buffer[y - 1], term_cols);
|
||||
memcpy(color_buffer[y], temp_color_buffer[y - 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(attr_buffer[y], temp_attr_buffer[y - 1],
|
||||
term_cols * sizeof(int));
|
||||
memcpy(bg_color_buffer[y], temp_bg_color_buffer[y - 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
// Clear the top line
|
||||
memset(terminal_buffer[0], ' ', term_cols);
|
||||
for (int x = 0; x < term_cols; x++) {
|
||||
color_buffer[0][x] = current_color;
|
||||
attr_buffer[0][x] = current_attr;
|
||||
bg_color_buffer[0][x] = current_bg_color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
memcpy(temp_buffer[i], terminal_buffer[i], term_cols * sizeof(char));
|
||||
memcpy(temp_color_buffer[i], color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(temp_attr_buffer[i], attr_buffer[i], term_cols * sizeof(int));
|
||||
memcpy(temp_bg_color_buffer[i], bg_color_buffer[i],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
for (int j = 0; j < amount; j++) {
|
||||
int start = (scroll_top - 1);
|
||||
int end = (scroll_bottom - 1);
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
if (end >= term_rows)
|
||||
end = term_rows - 1;
|
||||
|
||||
// Move all lines down one position
|
||||
for (int y = end; y > start; y--) {
|
||||
memcpy(terminal_buffer[y], temp_buffer[y - 1], term_cols);
|
||||
memcpy(color_buffer[y], temp_color_buffer[y - 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
memcpy(attr_buffer[y], temp_attr_buffer[y - 1],
|
||||
term_cols * sizeof(int));
|
||||
memcpy(bg_color_buffer[y], temp_bg_color_buffer[y - 1],
|
||||
term_cols * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
// Clear the top line
|
||||
memset(terminal_buffer[start], ' ', term_cols);
|
||||
for (int x = 0; x < term_cols; x++) {
|
||||
color_buffer[start][x] = current_color;
|
||||
attr_buffer[start][x] = current_attr;
|
||||
bg_color_buffer[start][x] = current_bg_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
free(temp_buffer[i]);
|
||||
free(temp_color_buffer[i]);
|
||||
free(temp_attr_buffer[i]);
|
||||
free(temp_bg_color_buffer[i]);
|
||||
}
|
||||
free(temp_buffer);
|
||||
free(temp_color_buffer);
|
||||
free(temp_attr_buffer);
|
||||
free(temp_bg_color_buffer);
|
||||
needs_refresh = 1;
|
||||
}
|
||||
|
||||
// Alternative buffer visual:
|
||||
//
|
||||
// Normal buffer: Alternate buffer:
|
||||
@ -453,7 +683,8 @@ static void scroll_up(void) {
|
||||
// saved_terminal = backup of normal buffer
|
||||
// saved_colors/attrs = backup of attributes
|
||||
// using_alternate = tracks which buffer is active
|
||||
static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
||||
static void handle_alternate_buffer(const char *buf, int *idx, int max_len,
|
||||
Window window) {
|
||||
char num_buf[32] = {0};
|
||||
size_t num_idx = 0;
|
||||
|
||||
@ -488,6 +719,8 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
||||
bg_color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||
}
|
||||
using_alternate = 1;
|
||||
needs_refresh = 1;
|
||||
draw_terminal(display, window);
|
||||
}
|
||||
} else if (using_alternate) {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
@ -506,6 +739,8 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
||||
bg_color_buffer = saved_colors;
|
||||
saved_terminal = NULL;
|
||||
using_alternate = 0;
|
||||
needs_refresh = 1;
|
||||
draw_terminal(display, window);
|
||||
}
|
||||
break;
|
||||
case 1048: // Save/restore cursor
|
||||
@ -537,6 +772,8 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
||||
bg_color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||
}
|
||||
using_alternate = 1;
|
||||
needs_refresh = 1;
|
||||
draw_terminal(display, window);
|
||||
}
|
||||
} else if (using_alternate) {
|
||||
for (int i = 0; i < term_rows; i++) {
|
||||
@ -557,6 +794,8 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
||||
cursor_x = saved_cursor_x;
|
||||
cursor_y = saved_cursor_y;
|
||||
using_alternate = 0;
|
||||
needs_refresh = 1;
|
||||
draw_terminal(display, window);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -583,7 +822,7 @@ static unsigned long get_bright_ansi_color(int index) {
|
||||
// 34 = Blue 35 = Magenta 36 = Cyan 37 = White
|
||||
// 0 sets everything back to plain white
|
||||
// P.S. yes I had to google this up
|
||||
static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
||||
static void parse_ansi_code(const char *buf, int *idx, int max_len, Window window) {
|
||||
char num_buf[32] = {0};
|
||||
int params[32] = {0};
|
||||
size_t num_idx = 0;
|
||||
@ -592,7 +831,7 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
||||
|
||||
// Handle '?' prefix for private sequences
|
||||
if (buf[*idx] == '?') {
|
||||
handle_alternate_buffer(buf, idx, max_len);
|
||||
handle_alternate_buffer(buf, idx, max_len, window);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -678,6 +917,54 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
||||
needs_refresh = 1;
|
||||
}
|
||||
break;
|
||||
case 'r': // Set scrolling region
|
||||
if (param_idx == 0) {
|
||||
scroll_top = 0; // Entire terminal
|
||||
scroll_bottom = 0;
|
||||
} else if (param_idx == 1) {
|
||||
scroll_top = (params[0] <= 0)
|
||||
? 1
|
||||
: (params[0] > term_rows ? term_rows : params[0]);
|
||||
scroll_bottom = 0;
|
||||
} else if (param_idx >= 2) {
|
||||
scroll_top = (params[0] <= 0)
|
||||
? 1
|
||||
: (params[0] > term_rows ? term_rows : params[0]);
|
||||
scroll_bottom = (params[1] <= 0)
|
||||
? term_rows
|
||||
: (params[1] > term_rows ? term_rows : params[1]);
|
||||
|
||||
// if top is bigger than bottom, swap values
|
||||
if (scroll_top > scroll_bottom) {
|
||||
int tmp = scroll_top;
|
||||
scroll_top = scroll_bottom;
|
||||
scroll_bottom = tmp;
|
||||
break;
|
||||
case 'S': // Scroll up
|
||||
scroll_region_up(params[0] == 0 ? 1 : params[0]);
|
||||
needs_refresh = 1;
|
||||
break;
|
||||
case 'T': // Scroll down
|
||||
scroll_region_down(params[0] == 0 ? 1 : params[0]);
|
||||
needs_refresh = 1;
|
||||
break;
|
||||
case 'E': // Cursor next line
|
||||
cursor_x = 0;
|
||||
cursor_y += params[0] ? params[0] : 1;
|
||||
if (cursor_y >= term_rows) {
|
||||
cursor_y = term_rows - 1;
|
||||
}
|
||||
break;
|
||||
case 'F': // Cursor line before
|
||||
cursor_x = 0;
|
||||
cursor_y -= params[0] ? params[0] : 1;
|
||||
if (cursor_y < 0) {
|
||||
cursor_y = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'm': // Handling of text
|
||||
for (int i = 0; i < param_idx; i++) {
|
||||
if (params[i] == 0) { // Reset Everything
|
||||
@ -722,7 +1009,7 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
||||
}
|
||||
}
|
||||
|
||||
static int master_cb(int fd, void *data) {
|
||||
static int master_cb(int fd, void *data, Window window) {
|
||||
if (!terminal_buffer || !color_buffer || !attr_buffer || !bg_color_buffer)
|
||||
return 0;
|
||||
char buf[4096];
|
||||
@ -740,7 +1027,7 @@ static int master_cb(int fd, void *data) {
|
||||
if (bytes_read > 0) {
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
if (buf[i] == '\033' && i + 1 < bytes_read && buf[i + 1] == '[') {
|
||||
parse_ansi_code(buf, &i, bytes_read);
|
||||
parse_ansi_code(buf, &i, bytes_read, window);
|
||||
continue;
|
||||
}
|
||||
if (buf[i] == '\n') {
|
||||
@ -1043,7 +1330,7 @@ int main(void) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(master, &fds);
|
||||
if (select(master + 1, &fds, NULL, NULL, &tv) > 0) {
|
||||
master_cb(master, &ctx);
|
||||
master_cb(master, &ctx, window);
|
||||
}
|
||||
|
||||
check_refresh(display, window);
|
||||
|
Loading…
Reference in New Issue
Block a user