ANSI Escape Code Handling
Better handling of ANSI Escape Code Handling
This commit is contained in:
parent
a044864f92
commit
264f53a342
143
cowterm.c
143
cowterm.c
@ -365,35 +365,16 @@ static void draw_terminal(Display *display, Window window) {
|
|||||||
if (!terminal_buffer || !color_buffer || !attr_buffer)
|
if (!terminal_buffer || !color_buffer || !attr_buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (buffer_pixmap == None)
|
XSetForeground(display, gc, current_bg_color);
|
||||||
buffer_pixmap = XCreatePixmap(
|
XFillRectangle(display, buffer_pixmap, gc, 0, 0, term_cols * CHAR_WIDTH,
|
||||||
display, DefaultRootWindow(display), term_cols * CHAR_WIDTH,
|
term_rows * CHAR_HEIGHT);
|
||||||
term_rows * CHAR_HEIGHT, DefaultDepth(display, DefaultScreen(display)));
|
|
||||||
|
|
||||||
if (needs_refresh) {
|
// Draw all characters
|
||||||
int start_y = scroll_top ? scroll_top - 1 : 0;
|
|
||||||
int end_y = scroll_bottom ? scroll_bottom : term_rows;
|
|
||||||
|
|
||||||
if (end_y > term_rows) {
|
|
||||||
end_y = term_rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scroll_top == 0 && scroll_bottom == 0) {
|
|
||||||
// Full screen refresh
|
|
||||||
for (int y = 0; y < term_rows; y++) {
|
for (int y = 0; y < term_rows; y++) {
|
||||||
for (int x = 0; x < term_cols; x++) {
|
for (int x = 0; x < term_cols; x++) {
|
||||||
draw_char(display, buffer_pixmap, x, y);
|
draw_char(display, buffer_pixmap, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Only refresh scroll region
|
|
||||||
for (int y = start_y; y < end_y; y++) {
|
|
||||||
for (int x = 0; x < term_cols; x++) {
|
|
||||||
draw_char(display, buffer_pixmap, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XCopyArea(display, buffer_pixmap, window, gc, 0, 0, term_cols * CHAR_WIDTH,
|
XCopyArea(display, buffer_pixmap, window, gc, 0, 0, term_cols * CHAR_WIDTH,
|
||||||
term_rows * CHAR_HEIGHT, 0, 0);
|
term_rows * CHAR_HEIGHT, 0, 0);
|
||||||
@ -745,6 +726,19 @@ static unsigned long get_bright_ansi_color(int index) {
|
|||||||
// P.S. yes I had to google this up
|
// 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) {
|
Window window) {
|
||||||
|
if (*idx + 1 < max_len) {
|
||||||
|
// Skip CSI sequences that we don't need to process
|
||||||
|
if (buf[*idx] == '\033' && buf[*idx + 1] == '(') {
|
||||||
|
*idx += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Skip other common terminal sequences
|
||||||
|
if (buf[*idx] == '\033' && strchr("=>", buf[*idx + 1])) {
|
||||||
|
*idx += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char num_buf[32] = {0};
|
char num_buf[32] = {0};
|
||||||
int params[32] = {0};
|
int params[32] = {0};
|
||||||
size_t num_idx = 0;
|
size_t num_idx = 0;
|
||||||
@ -911,15 +905,76 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len,
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case 'K': // Clear line
|
case 'K': // Clear line
|
||||||
for (int i = cursor_x; i < term_cols; i++) {
|
switch (params[0]) {
|
||||||
terminal_buffer[cursor_y][i] = ' ';
|
case 0: // Clear from cursor to end of line
|
||||||
color_buffer[cursor_y][i] = current_color;
|
for (int x = cursor_x; x < term_cols; x++) {
|
||||||
attr_buffer[cursor_y][i] = current_attr;
|
terminal_buffer[cursor_y][x] = ' ';
|
||||||
bg_color_buffer[cursor_y][i] = current_bg_color;
|
color_buffer[cursor_y][x] = current_color;
|
||||||
|
attr_buffer[cursor_y][x] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 1: // Clear from cursor to beginning of line
|
||||||
|
for (int x = 0; x <= cursor_x; x++) {
|
||||||
|
terminal_buffer[cursor_y][x] = ' ';
|
||||||
|
color_buffer[cursor_y][x] = current_color;
|
||||||
|
attr_buffer[cursor_y][x] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // Clear entire line
|
||||||
|
memset(terminal_buffer[cursor_y], ' ', term_cols);
|
||||||
|
for (int x = 0; x < term_cols; x++) {
|
||||||
|
color_buffer[cursor_y][x] = current_color;
|
||||||
|
attr_buffer[cursor_y][x] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
case 'J': // Clear screen
|
case 'J': // Clear screen
|
||||||
if (params[0] == 2) {
|
switch (params[0]) {
|
||||||
|
case 0: // Clear from cursor to end of screen
|
||||||
|
// Clear current line from cursor
|
||||||
|
for (int x = cursor_x; x < term_cols; x++) {
|
||||||
|
terminal_buffer[cursor_y][x] = ' ';
|
||||||
|
color_buffer[cursor_y][x] = current_color;
|
||||||
|
attr_buffer[cursor_y][x] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
// Clear all lines below cursor
|
||||||
|
for (int y = cursor_y + 1; y < term_rows; y++) {
|
||||||
|
memset(terminal_buffer[y], ' ', term_cols);
|
||||||
|
for (int x = 0; x < term_cols; x++) {
|
||||||
|
color_buffer[y][x] = current_color;
|
||||||
|
attr_buffer[y][x] = current_attr;
|
||||||
|
bg_color_buffer[y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
|
case 1: // Clear from cursor to beginning of screen
|
||||||
|
// Clear current line up to cursor
|
||||||
|
for (int x = 0; x <= cursor_x; x++) {
|
||||||
|
terminal_buffer[cursor_y][x] = ' ';
|
||||||
|
color_buffer[cursor_y][x] = current_color;
|
||||||
|
attr_buffer[cursor_y][x] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
// Clear all lines above cursor
|
||||||
|
for (int y = 0; y < cursor_y; y++) {
|
||||||
|
memset(terminal_buffer[y], ' ', term_cols);
|
||||||
|
for (int x = 0; x < term_cols; x++) {
|
||||||
|
color_buffer[y][x] = current_color;
|
||||||
|
attr_buffer[y][x] = current_attr;
|
||||||
|
bg_color_buffer[y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
|
case 2: // Clear entire screen
|
||||||
|
case 3: // Clear entire screen and scrollback (treat same as 2)
|
||||||
current_color = XWhitePixel(display, DefaultScreen(display));
|
current_color = XWhitePixel(display, DefaultScreen(display));
|
||||||
current_bg_color = XBlackPixel(display, DefaultScreen(display));
|
current_bg_color = XBlackPixel(display, DefaultScreen(display));
|
||||||
current_attr = 0;
|
current_attr = 0;
|
||||||
@ -932,6 +987,7 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r': // Set scrolling region
|
case 'r': // Set scrolling region
|
||||||
@ -1051,10 +1107,34 @@ static int master_cb(int fd, void *data, Window window) {
|
|||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (buf[i] == '\033' && i + 1 < n && buf[i + 1] == '[') {
|
if (buf[i] == '\033') {
|
||||||
|
if (i + 1 < n && buf[i + 1] == '[') {
|
||||||
parse_ansi_code(buf, &i, n, window);
|
parse_ansi_code(buf, &i, n, window);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (i + 1 < n && (buf[i + 1] == '(' || buf[i + 1] == ')')) {
|
||||||
|
if (i + 2 < n) {
|
||||||
|
i += 2; // Skip ESC, (, and the character set identifier
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Handle other simple escape sequences
|
||||||
|
if (i + 1 < n) {
|
||||||
|
switch (buf[i + 1]) {
|
||||||
|
case '=': // Application keypad
|
||||||
|
case '>': // Normal keypad
|
||||||
|
case '7': // Save cursor position
|
||||||
|
case '8': // Restore cursor position
|
||||||
|
case 'E': // Next line
|
||||||
|
case 'M': // Reverse line feed
|
||||||
|
i++; // Skip the command character
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((buf[i] >= 32 && buf[i] <= 126) || buf[i] == '\n' || buf[i] == '\r' ||
|
||||||
|
buf[i] == '\b' || buf[i] == '\t') {
|
||||||
switch (buf[i]) {
|
switch (buf[i]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
cursor_x = 0;
|
cursor_x = 0;
|
||||||
@ -1086,7 +1166,7 @@ static int master_cb(int fd, void *data, Window window) {
|
|||||||
default:
|
default:
|
||||||
if (cursor_y >= term_rows || cursor_x >= term_cols)
|
if (cursor_y >= term_rows || cursor_x >= term_cols)
|
||||||
break;
|
break;
|
||||||
if (buf[i] >= 32 && buf[i] <= 126) {
|
if ((buf[i] >= 32 && buf[i] <= 126) || buf[i] == '\t') {
|
||||||
terminal_buffer[cursor_y][cursor_x] = buf[i];
|
terminal_buffer[cursor_y][cursor_x] = buf[i];
|
||||||
color_buffer[cursor_y][cursor_x] = current_color;
|
color_buffer[cursor_y][cursor_x] = current_color;
|
||||||
attr_buffer[cursor_y][cursor_x] = current_attr;
|
attr_buffer[cursor_y][cursor_x] = current_attr;
|
||||||
@ -1103,6 +1183,7 @@ static int master_cb(int fd, void *data, Window window) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cursor_visible = 1;
|
cursor_visible = 1;
|
||||||
if (needs_refresh)
|
if (needs_refresh)
|
||||||
check_refresh(ctx->display, ctx->window);
|
check_refresh(ctx->display, ctx->window);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user