Added highlighting, diming support
htop looks a lot better now
This commit is contained in:
parent
e7cb69fe4b
commit
d53f948bc4
@ -12,7 +12,7 @@ LIBS = -L/usr/X11R6/lib -lX11 -lutil ${FREETYPELIBS}
|
|||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
|
||||||
CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os ${INCS} ${CPPFLAGS}
|
CFLAGS = -g -std=c99 -pedantic -Wall -Wextra -Os ${INCS} ${CPPFLAGS}
|
||||||
LDFLAGS = ${LIBS}
|
LDFLAGS = ${LIBS}
|
||||||
|
|
||||||
# compiler and linker
|
# compiler and linker
|
||||||
|
249
cowterm.c
249
cowterm.c
@ -23,29 +23,36 @@
|
|||||||
#define CHAR_WIDTH 8
|
#define CHAR_WIDTH 8
|
||||||
#define CHAR_HEIGHT 16
|
#define CHAR_HEIGHT 16
|
||||||
|
|
||||||
|
// General window/terminal stuff
|
||||||
static pid_t child_pid;
|
static pid_t child_pid;
|
||||||
static char **terminal_buffer = NULL;
|
static char **terminal_buffer = NULL;
|
||||||
static unsigned long **color_buffer = NULL;
|
static unsigned long **color_buffer = NULL;
|
||||||
static int **attr_buffer = NULL;
|
static int **attr_buffer = NULL;
|
||||||
static int term_rows;
|
static int term_rows;
|
||||||
static int term_cols;
|
static int term_cols;
|
||||||
static int cursor_x = 0;
|
|
||||||
static int cursor_y = 0;
|
|
||||||
static unsigned long current_color;
|
static unsigned long current_color;
|
||||||
static int current_attr = 0;
|
static int current_attr = 0;
|
||||||
static GC gc = NULL;
|
static GC gc = NULL;
|
||||||
static GC gc_bold = NULL;
|
static GC gc_bold = NULL;
|
||||||
static Display *display = NULL;
|
static Display *display = NULL;
|
||||||
static int cursor_visible = 1;
|
|
||||||
static struct timeval last_blink;
|
|
||||||
static struct timeval last_refresh;
|
static struct timeval last_refresh;
|
||||||
static Pixmap buffer_pixmap = None;
|
static Pixmap buffer_pixmap = None;
|
||||||
static int master_fd = -1;
|
static int master_fd = -1;
|
||||||
static int needs_refresh = 0;
|
static int needs_refresh = 0;
|
||||||
|
static int window_focused = 0;
|
||||||
|
|
||||||
|
// Cursor stuff
|
||||||
|
static int cursor_visible = 1;
|
||||||
|
static struct timeval last_blink;
|
||||||
|
static int cursor_x = 0;
|
||||||
|
static int cursor_y = 0;
|
||||||
|
|
||||||
|
// Font stuff
|
||||||
static XFontStruct *regular_font = NULL;
|
static XFontStruct *regular_font = NULL;
|
||||||
static XFontStruct *bold_font = NULL;
|
static XFontStruct *bold_font = NULL;
|
||||||
static XFontStruct *italic_font = NULL;
|
static XFontStruct *italic_font = NULL;
|
||||||
static int window_focused = 0;
|
static unsigned long current_bg_color;
|
||||||
|
static unsigned long **bg_color_buffer = NULL;
|
||||||
|
|
||||||
// Alternatives to handle the ANSI escape codes
|
// Alternatives to handle the ANSI escape codes
|
||||||
static char **saved_terminal = NULL;
|
static char **saved_terminal = NULL;
|
||||||
@ -55,8 +62,12 @@ static int saved_cursor_x = 0;
|
|||||||
static int saved_cursor_y = 0;
|
static int saved_cursor_y = 0;
|
||||||
static int using_alternate = 0;
|
static int using_alternate = 0;
|
||||||
|
|
||||||
#define ATTR_BOLD 1
|
#define ATTR_BOLD (1 << 0)
|
||||||
#define ATTR_ITALIC 2
|
#define ATTR_ITALIC (1 << 1)
|
||||||
|
#define ATTR_REVERSE (1 << 2)
|
||||||
|
#define ATTR_UNDERLINE (1 << 3)
|
||||||
|
#define ATTR_DIM (1 << 4)
|
||||||
|
#define ATTR_BLINK (1 << 5)
|
||||||
|
|
||||||
// Pesky static smth smth error, so we "declare" it early
|
// Pesky static smth smth error, so we "declare" it early
|
||||||
static void draw_terminal(Display *display, Window window);
|
static void draw_terminal(Display *display, Window window);
|
||||||
@ -144,12 +155,16 @@ static void resize_buffers(int new_rows, int new_cols) {
|
|||||||
size_t row_size = ((new_cols * sizeof(char) + 15) & ~15);
|
size_t row_size = ((new_cols * sizeof(char) + 15) & ~15);
|
||||||
size_t color_row_size = ((new_cols * sizeof(unsigned long) + 15) & ~15);
|
size_t color_row_size = ((new_cols * sizeof(unsigned long) + 15) & ~15);
|
||||||
size_t attr_row_size = ((new_cols * sizeof(int) + 15) & ~15);
|
size_t attr_row_size = ((new_cols * sizeof(int) + 15) & ~15);
|
||||||
|
size_t bg_color_row_size = ((new_cols * sizeof(unsigned long) + 15) & ~15);
|
||||||
|
|
||||||
char **new_term_buffer = malloc(new_rows * sizeof(char *));
|
char **new_term_buffer = malloc(new_rows * sizeof(char *));
|
||||||
unsigned long **new_color_buffer = malloc(new_rows * sizeof(unsigned long *));
|
unsigned long **new_color_buffer = malloc(new_rows * sizeof(unsigned long *));
|
||||||
int **new_attr_buffer = malloc(new_rows * sizeof(int *));
|
int **new_attr_buffer = malloc(new_rows * sizeof(int *));
|
||||||
|
unsigned long **new_bg_color_buffer =
|
||||||
|
malloc(new_rows * sizeof(unsigned long *));
|
||||||
|
|
||||||
if (!new_term_buffer || !new_color_buffer || !new_attr_buffer) {
|
if (!new_term_buffer || !new_color_buffer || !new_attr_buffer ||
|
||||||
|
!new_bg_color_buffer) {
|
||||||
fprintf(stderr, "Failed to allocate memory for buffers\n");
|
fprintf(stderr, "Failed to allocate memory for buffers\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -158,33 +173,40 @@ static void resize_buffers(int new_rows, int new_cols) {
|
|||||||
new_term_buffer[i] = malloc(row_size);
|
new_term_buffer[i] = malloc(row_size);
|
||||||
new_color_buffer[i] = malloc(color_row_size);
|
new_color_buffer[i] = malloc(color_row_size);
|
||||||
new_attr_buffer[i] = malloc(attr_row_size);
|
new_attr_buffer[i] = malloc(attr_row_size);
|
||||||
|
new_bg_color_buffer[i] = malloc(bg_color_row_size);
|
||||||
|
|
||||||
if (!new_term_buffer[i] || !new_color_buffer[i] || !new_attr_buffer[i]) {
|
if (!new_term_buffer[i] || !new_color_buffer[i] || !new_attr_buffer[i] ||
|
||||||
|
!new_bg_color_buffer[i]) {
|
||||||
fprintf(stderr, "Failed to allocate memory for buffer row\n");
|
fprintf(stderr, "Failed to allocate memory for buffer row\n");
|
||||||
// Clean up allocated memory
|
// Clean up allocated memory
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
free(new_term_buffer[j]);
|
free(new_term_buffer[j]);
|
||||||
free(new_color_buffer[j]);
|
free(new_color_buffer[j]);
|
||||||
free(new_attr_buffer[j]);
|
free(new_attr_buffer[j]);
|
||||||
|
free(new_bg_color_buffer[j]);
|
||||||
}
|
}
|
||||||
free(new_term_buffer);
|
free(new_term_buffer);
|
||||||
free(new_color_buffer);
|
free(new_color_buffer);
|
||||||
free(new_attr_buffer);
|
free(new_attr_buffer);
|
||||||
|
free(new_bg_color_buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < term_rows && i < new_rows && terminal_buffer && color_buffer &&
|
if (i < term_rows && i < new_rows && terminal_buffer && color_buffer &&
|
||||||
attr_buffer) {
|
attr_buffer && bg_color_buffer) {
|
||||||
int copy_cols = (new_cols < term_cols) ? new_cols : term_cols;
|
int copy_cols = (new_cols < term_cols) ? new_cols : term_cols;
|
||||||
memcpy(new_term_buffer[i], terminal_buffer[i], copy_cols * sizeof(char));
|
memcpy(new_term_buffer[i], terminal_buffer[i], copy_cols * sizeof(char));
|
||||||
memcpy(new_color_buffer[i], color_buffer[i],
|
memcpy(new_color_buffer[i], color_buffer[i],
|
||||||
copy_cols * sizeof(unsigned long));
|
copy_cols * sizeof(unsigned long));
|
||||||
memcpy(new_attr_buffer[i], attr_buffer[i], copy_cols * sizeof(int));
|
memcpy(new_attr_buffer[i], attr_buffer[i], copy_cols * sizeof(int));
|
||||||
|
memcpy(new_bg_color_buffer[i], bg_color_buffer[i],
|
||||||
|
copy_cols * sizeof(unsigned long));
|
||||||
if (new_cols > term_cols) {
|
if (new_cols > term_cols) {
|
||||||
memset(new_term_buffer[i] + term_cols, ' ', new_cols - term_cols);
|
memset(new_term_buffer[i] + term_cols, ' ', new_cols - term_cols);
|
||||||
for (int x = term_cols; x < new_cols; x++) {
|
for (int x = term_cols; x < new_cols; x++) {
|
||||||
new_color_buffer[i][x] = current_color;
|
new_color_buffer[i][x] = current_color;
|
||||||
new_attr_buffer[i][x] = current_attr;
|
new_attr_buffer[i][x] = current_attr;
|
||||||
|
new_bg_color_buffer[i][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -192,25 +214,29 @@ static void resize_buffers(int new_rows, int new_cols) {
|
|||||||
for (int x = 0; x < new_cols; x++) {
|
for (int x = 0; x < new_cols; x++) {
|
||||||
new_color_buffer[i][x] = current_color;
|
new_color_buffer[i][x] = current_color;
|
||||||
new_attr_buffer[i][x] = current_attr;
|
new_attr_buffer[i][x] = current_attr;
|
||||||
|
new_bg_color_buffer[i][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free old buffers after successful allocation
|
// Free old buffers after successful allocation
|
||||||
if (terminal_buffer && color_buffer && attr_buffer) {
|
if (terminal_buffer && color_buffer && attr_buffer && bg_color_buffer) {
|
||||||
for (int i = 0; i < term_rows; i++) {
|
for (int i = 0; i < term_rows; i++) {
|
||||||
free(terminal_buffer[i]);
|
free(terminal_buffer[i]);
|
||||||
free(color_buffer[i]);
|
free(color_buffer[i]);
|
||||||
free(attr_buffer[i]);
|
free(attr_buffer[i]);
|
||||||
|
free(bg_color_buffer[i]);
|
||||||
}
|
}
|
||||||
free(terminal_buffer);
|
free(terminal_buffer);
|
||||||
free(color_buffer);
|
free(color_buffer);
|
||||||
free(attr_buffer);
|
free(attr_buffer);
|
||||||
|
free(bg_color_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_buffer = new_term_buffer;
|
terminal_buffer = new_term_buffer;
|
||||||
color_buffer = new_color_buffer;
|
color_buffer = new_color_buffer;
|
||||||
attr_buffer = new_attr_buffer;
|
attr_buffer = new_attr_buffer;
|
||||||
|
bg_color_buffer = new_bg_color_buffer;
|
||||||
term_rows = new_rows;
|
term_rows = new_rows;
|
||||||
term_cols = new_cols;
|
term_cols = new_cols;
|
||||||
|
|
||||||
@ -258,24 +284,41 @@ static void destroy_cb(Display *display, Window window) {
|
|||||||
}
|
}
|
||||||
free(attr_buffer);
|
free(attr_buffer);
|
||||||
}
|
}
|
||||||
|
if (bg_color_buffer) {
|
||||||
|
for (int i = 0; i < term_rows; i++) {
|
||||||
|
free(bg_color_buffer[i]);
|
||||||
|
}
|
||||||
|
free(bg_color_buffer);
|
||||||
|
}
|
||||||
if (master_fd >= 0)
|
if (master_fd >= 0)
|
||||||
close(master_fd);
|
close(master_fd);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_char(Display *display, Drawable d, int x, int y) {
|
static void draw_char(Display *display, Drawable d, int x, int y) {
|
||||||
if (!gc || !terminal_buffer || !color_buffer || !attr_buffer)
|
if (!gc || !terminal_buffer || !color_buffer || !attr_buffer ||
|
||||||
|
!bg_color_buffer)
|
||||||
return;
|
return;
|
||||||
if (x < 0 || x >= term_cols || y < 0 || y >= term_rows)
|
if (x < 0 || x >= term_cols || y < 0 || y >= term_rows)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
unsigned long fg_color = color_buffer[y][x];
|
||||||
|
unsigned long bg_color = bg_color_buffer[y][x];
|
||||||
|
int attrs = attr_buffer[y][x];
|
||||||
|
|
||||||
|
if (attrs & ATTR_REVERSE) {
|
||||||
|
unsigned long temp = fg_color;
|
||||||
|
fg_color = bg_color;
|
||||||
|
bg_color = temp;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear the character position first
|
// Clear the character position first
|
||||||
XSetForeground(display, gc, XBlackPixel(display, DefaultScreen(display)));
|
XSetForeground(display, gc, bg_color);
|
||||||
XFillRectangle(display, d, gc, x * CHAR_WIDTH, y * CHAR_HEIGHT, CHAR_WIDTH,
|
XFillRectangle(display, d, gc, x * CHAR_WIDTH, y * CHAR_HEIGHT, CHAR_WIDTH,
|
||||||
CHAR_HEIGHT);
|
CHAR_HEIGHT);
|
||||||
|
XSetForeground(display, gc, fg_color);
|
||||||
|
|
||||||
char str[2] = {terminal_buffer[y][x], '\0'};
|
char str[2] = {terminal_buffer[y][x], '\0'};
|
||||||
XSetForeground(display, gc, color_buffer[y][x]);
|
|
||||||
|
|
||||||
// Select appropriate font based on attributes
|
// Select appropriate font based on attributes
|
||||||
XFontStruct *font = regular_font;
|
XFontStruct *font = regular_font;
|
||||||
@ -288,6 +331,11 @@ static void draw_char(Display *display, Drawable d, int x, int y) {
|
|||||||
|
|
||||||
XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 2, str,
|
XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 2, str,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
|
if (attrs & ATTR_UNDERLINE) {
|
||||||
|
XDrawLine(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 1,
|
||||||
|
(x + 1) * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_terminal(Display *display, Window window) {
|
static void draw_terminal(Display *display, Window window) {
|
||||||
@ -350,13 +398,14 @@ static void check_refresh(Display *display, Window window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void clear_terminal(Display *display, Window window) {
|
static void clear_terminal(Display *display, Window window) {
|
||||||
if (!terminal_buffer || !color_buffer || !attr_buffer)
|
if (!terminal_buffer || !color_buffer || !attr_buffer || !bg_color_buffer)
|
||||||
return;
|
return;
|
||||||
for (int y = 0; y < term_rows; y++) {
|
for (int y = 0; y < term_rows; y++) {
|
||||||
memset(terminal_buffer[y], ' ', term_cols);
|
memset(terminal_buffer[y], ' ', term_cols);
|
||||||
for (int x = 0; x < term_cols; x++) {
|
for (int x = 0; x < term_cols; x++) {
|
||||||
color_buffer[y][x] = current_color;
|
color_buffer[y][x] = current_color;
|
||||||
attr_buffer[y][x] = current_attr;
|
attr_buffer[y][x] = current_attr;
|
||||||
|
bg_color_buffer[y][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor_x = 0;
|
cursor_x = 0;
|
||||||
@ -372,6 +421,8 @@ static void scroll_up(void) {
|
|||||||
memcpy(color_buffer[y], color_buffer[y + 1],
|
memcpy(color_buffer[y], color_buffer[y + 1],
|
||||||
term_cols * sizeof(unsigned long));
|
term_cols * sizeof(unsigned long));
|
||||||
memcpy(attr_buffer[y], attr_buffer[y + 1], term_cols * sizeof(int));
|
memcpy(attr_buffer[y], attr_buffer[y + 1], term_cols * sizeof(int));
|
||||||
|
memcpy(bg_color_buffer[y], bg_color_buffer[y + 1],
|
||||||
|
term_cols * sizeof(unsigned long));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the bottom line
|
// Clear the bottom line
|
||||||
@ -379,6 +430,7 @@ static void scroll_up(void) {
|
|||||||
for (int x = 0; x < term_cols; x++) {
|
for (int x = 0; x < term_cols; x++) {
|
||||||
color_buffer[term_rows - 1][x] = current_color;
|
color_buffer[term_rows - 1][x] = current_color;
|
||||||
attr_buffer[term_rows - 1][x] = current_attr;
|
attr_buffer[term_rows - 1][x] = current_attr;
|
||||||
|
bg_color_buffer[term_rows - 1][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
}
|
}
|
||||||
@ -424,13 +476,16 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
|||||||
saved_terminal = terminal_buffer;
|
saved_terminal = terminal_buffer;
|
||||||
saved_colors = color_buffer;
|
saved_colors = color_buffer;
|
||||||
saved_attrs = attr_buffer;
|
saved_attrs = attr_buffer;
|
||||||
|
saved_colors = bg_color_buffer;
|
||||||
terminal_buffer = malloc(term_rows * sizeof(char *));
|
terminal_buffer = malloc(term_rows * sizeof(char *));
|
||||||
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
attr_buffer = malloc(term_rows * sizeof(int *));
|
attr_buffer = malloc(term_rows * sizeof(int *));
|
||||||
|
bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
for (int i = 0; i < term_rows; i++) {
|
for (int i = 0; i < term_rows; i++) {
|
||||||
terminal_buffer[i] = calloc(term_cols, sizeof(char));
|
terminal_buffer[i] = calloc(term_cols, sizeof(char));
|
||||||
color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||||
attr_buffer[i] = calloc(term_cols, sizeof(int));
|
attr_buffer[i] = calloc(term_cols, sizeof(int));
|
||||||
|
bg_color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||||
}
|
}
|
||||||
using_alternate = 1;
|
using_alternate = 1;
|
||||||
}
|
}
|
||||||
@ -439,13 +494,16 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
|||||||
free(terminal_buffer[i]);
|
free(terminal_buffer[i]);
|
||||||
free(color_buffer[i]);
|
free(color_buffer[i]);
|
||||||
free(attr_buffer[i]);
|
free(attr_buffer[i]);
|
||||||
|
free(bg_color_buffer[i]);
|
||||||
}
|
}
|
||||||
free(terminal_buffer);
|
free(terminal_buffer);
|
||||||
free(color_buffer);
|
free(color_buffer);
|
||||||
free(attr_buffer);
|
free(attr_buffer);
|
||||||
|
free(bg_color_buffer);
|
||||||
terminal_buffer = saved_terminal;
|
terminal_buffer = saved_terminal;
|
||||||
color_buffer = saved_colors;
|
color_buffer = saved_colors;
|
||||||
attr_buffer = saved_attrs;
|
attr_buffer = saved_attrs;
|
||||||
|
bg_color_buffer = saved_colors;
|
||||||
saved_terminal = NULL;
|
saved_terminal = NULL;
|
||||||
using_alternate = 0;
|
using_alternate = 0;
|
||||||
}
|
}
|
||||||
@ -467,13 +525,16 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
|||||||
saved_terminal = terminal_buffer;
|
saved_terminal = terminal_buffer;
|
||||||
saved_colors = color_buffer;
|
saved_colors = color_buffer;
|
||||||
saved_attrs = attr_buffer;
|
saved_attrs = attr_buffer;
|
||||||
|
saved_colors = bg_color_buffer;
|
||||||
terminal_buffer = malloc(term_rows * sizeof(char *));
|
terminal_buffer = malloc(term_rows * sizeof(char *));
|
||||||
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
attr_buffer = malloc(term_rows * sizeof(int *));
|
attr_buffer = malloc(term_rows * sizeof(int *));
|
||||||
|
bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
for (int i = 0; i < term_rows; i++) {
|
for (int i = 0; i < term_rows; i++) {
|
||||||
terminal_buffer[i] = calloc(term_cols, sizeof(char));
|
terminal_buffer[i] = calloc(term_cols, sizeof(char));
|
||||||
color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||||
attr_buffer[i] = calloc(term_cols, sizeof(int));
|
attr_buffer[i] = calloc(term_cols, sizeof(int));
|
||||||
|
bg_color_buffer[i] = calloc(term_cols, sizeof(unsigned long));
|
||||||
}
|
}
|
||||||
using_alternate = 1;
|
using_alternate = 1;
|
||||||
}
|
}
|
||||||
@ -482,13 +543,16 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
|||||||
free(terminal_buffer[i]);
|
free(terminal_buffer[i]);
|
||||||
free(color_buffer[i]);
|
free(color_buffer[i]);
|
||||||
free(attr_buffer[i]);
|
free(attr_buffer[i]);
|
||||||
|
free(bg_color_buffer[i]);
|
||||||
}
|
}
|
||||||
free(terminal_buffer);
|
free(terminal_buffer);
|
||||||
free(color_buffer);
|
free(color_buffer);
|
||||||
free(attr_buffer);
|
free(attr_buffer);
|
||||||
|
free(bg_color_buffer);
|
||||||
terminal_buffer = saved_terminal;
|
terminal_buffer = saved_terminal;
|
||||||
color_buffer = saved_colors;
|
color_buffer = saved_colors;
|
||||||
attr_buffer = saved_attrs;
|
attr_buffer = saved_attrs;
|
||||||
|
bg_color_buffer = saved_colors;
|
||||||
saved_terminal = NULL;
|
saved_terminal = NULL;
|
||||||
cursor_x = saved_cursor_x;
|
cursor_x = saved_cursor_x;
|
||||||
cursor_y = saved_cursor_y;
|
cursor_y = saved_cursor_y;
|
||||||
@ -500,6 +564,19 @@ static void handle_alternate_buffer(const char *buf, int *idx, int max_len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long get_ansi_color(int index) {
|
||||||
|
static const unsigned long colors[] = {0x000000, RED, GREEN, YELLOW,
|
||||||
|
BLUE, MAGENTA, CYAN, 0xFFFFFF};
|
||||||
|
return colors[index & 7];
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long get_bright_ansi_color(int index) {
|
||||||
|
static const unsigned long colors[] = {
|
||||||
|
DARK_GRAY, LIGHT_RED, LIGHT_GREEN, LIGHT_YELLOW,
|
||||||
|
LIGHT_BLUE, LIGHT_MAGENTA, LIGHT_CYAN, 0xFFFFFF};
|
||||||
|
return colors[index & 7];
|
||||||
|
}
|
||||||
|
|
||||||
// Handles those pesky ANSI color escape codes that terminals use.
|
// Handles those pesky ANSI color escape codes that terminals use.
|
||||||
// When \033[<number>m is sent to the terminal, it changes text color:
|
// When \033[<number>m is sent to the terminal, it changes text color:
|
||||||
// 30 = Black 31 = Red 32 = Green 33 = Yellow
|
// 30 = Black 31 = Red 32 = Green 33 = Yellow
|
||||||
@ -585,6 +662,7 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
|||||||
terminal_buffer[cursor_y][i] = ' ';
|
terminal_buffer[cursor_y][i] = ' ';
|
||||||
color_buffer[cursor_y][i] = current_color;
|
color_buffer[cursor_y][i] = current_color;
|
||||||
attr_buffer[cursor_y][i] = current_attr;
|
attr_buffer[cursor_y][i] = current_attr;
|
||||||
|
bg_color_buffer[cursor_y][i] = current_bg_color;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'J': // Clear screen
|
case 'J': // Clear screen
|
||||||
@ -594,6 +672,7 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
|||||||
for (int x = 0; x < term_cols; x++) {
|
for (int x = 0; x < term_cols; x++) {
|
||||||
color_buffer[y][x] = current_color;
|
color_buffer[y][x] = current_color;
|
||||||
attr_buffer[y][x] = current_attr;
|
attr_buffer[y][x] = current_attr;
|
||||||
|
bg_color_buffer[y][x] = current_bg_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
@ -601,71 +680,40 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len) {
|
|||||||
break;
|
break;
|
||||||
case 'm': // Handling of text
|
case 'm': // Handling of text
|
||||||
for (int i = 0; i < param_idx; i++) {
|
for (int i = 0; i < param_idx; i++) {
|
||||||
switch (params[i]) {
|
if (params[i] == 0) { // Reset Everything
|
||||||
case 0:
|
|
||||||
current_color = XWhitePixel(display, DefaultScreen(display));
|
current_color = XWhitePixel(display, DefaultScreen(display));
|
||||||
|
current_bg_color = XBlackPixel(display, DefaultScreen(display));
|
||||||
current_attr = 0;
|
current_attr = 0;
|
||||||
break;
|
} else if (params[i] == 1) { // Apply ATTRS
|
||||||
case 1:
|
|
||||||
current_attr |= ATTR_BOLD;
|
current_attr |= ATTR_BOLD;
|
||||||
break;
|
} else if (params[i] == 2) {
|
||||||
case 3:
|
current_attr |= ATTR_DIM;
|
||||||
|
} else if (params[i] == 3) {
|
||||||
current_attr |= ATTR_ITALIC;
|
current_attr |= ATTR_ITALIC;
|
||||||
break;
|
} else if (params[i] == 4) {
|
||||||
case 22:
|
current_attr |= ATTR_UNDERLINE;
|
||||||
|
} else if (params[i] == 5) {
|
||||||
|
current_attr |= ATTR_BLINK;
|
||||||
|
} else if (params[i] == 7) {
|
||||||
|
current_attr |= ATTR_REVERSE;
|
||||||
|
} else if (params[i] == 22) { // Reset ATTRS
|
||||||
current_attr &= ~ATTR_BOLD;
|
current_attr &= ~ATTR_BOLD;
|
||||||
break;
|
} else if (params[i] == 23) {
|
||||||
case 23:
|
|
||||||
current_attr &= ~ATTR_ITALIC;
|
current_attr &= ~ATTR_ITALIC;
|
||||||
break;
|
} else if (params[i] == 24) {
|
||||||
case 30:
|
current_attr &= ~ATTR_UNDERLINE;
|
||||||
current_color = XBlackPixel(display, DefaultScreen(display));
|
} else if (params[i] == 27) {
|
||||||
break;
|
current_attr &= ~ATTR_REVERSE;
|
||||||
case 31:
|
} else if (params[i] >= 30 && params[i] <= 37) { // Foreground colors
|
||||||
current_color = RED;
|
current_color = get_ansi_color(params[i] - 30);
|
||||||
break;
|
} else if (params[i] >= 40 && params[i] <= 47) { // Background colors
|
||||||
case 32:
|
current_bg_color = get_ansi_color(params[i] - 40);
|
||||||
current_color = GREEN;
|
} else if (params[i] >= 90 &&
|
||||||
break;
|
params[i] <= 97) { // Bright foreground colors
|
||||||
case 33:
|
current_color = get_bright_ansi_color(params[i] - 90);
|
||||||
current_color = YELLOW;
|
} else if (params[i] >= 100 &&
|
||||||
break;
|
params[i] <= 107) { // Bright background colors
|
||||||
case 34:
|
current_bg_color = get_bright_ansi_color(params[i] - 100);
|
||||||
current_color = BLUE;
|
|
||||||
break;
|
|
||||||
case 35:
|
|
||||||
current_color = MAGENTA;
|
|
||||||
break;
|
|
||||||
case 36:
|
|
||||||
current_color = CYAN;
|
|
||||||
break;
|
|
||||||
case 37:
|
|
||||||
current_color = XWhitePixel(display, DefaultScreen(display));
|
|
||||||
break;
|
|
||||||
case 90:
|
|
||||||
current_color = DARK_GRAY;
|
|
||||||
break;
|
|
||||||
case 91:
|
|
||||||
current_color = LIGHT_RED;
|
|
||||||
break;
|
|
||||||
case 92:
|
|
||||||
current_color = LIGHT_GREEN;
|
|
||||||
break;
|
|
||||||
case 93:
|
|
||||||
current_color = LIGHT_YELLOW;
|
|
||||||
break;
|
|
||||||
case 94:
|
|
||||||
current_color = LIGHT_BLUE;
|
|
||||||
break;
|
|
||||||
case 95:
|
|
||||||
current_color = LIGHT_MAGENTA;
|
|
||||||
break;
|
|
||||||
case 96:
|
|
||||||
current_color = LIGHT_CYAN;
|
|
||||||
break;
|
|
||||||
case 97:
|
|
||||||
current_color = 0xFFFFFF;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -673,7 +721,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) {
|
||||||
if (!terminal_buffer || !color_buffer || !attr_buffer)
|
if (!terminal_buffer || !color_buffer || !attr_buffer || !bg_color_buffer)
|
||||||
return 0;
|
return 0;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
@ -699,8 +747,8 @@ static int master_cb(int fd, void *data) {
|
|||||||
if (cursor_y >= term_rows) {
|
if (cursor_y >= term_rows) {
|
||||||
scroll_up();
|
scroll_up();
|
||||||
cursor_y = term_rows - 1;
|
cursor_y = term_rows - 1;
|
||||||
needs_refresh = 1;
|
|
||||||
}
|
}
|
||||||
|
needs_refresh = 1;
|
||||||
} else if (buf[i] == '\r') {
|
} else if (buf[i] == '\r') {
|
||||||
cursor_x = 0;
|
cursor_x = 0;
|
||||||
} else if (buf[i] == '\b') {
|
} else if (buf[i] == '\b') {
|
||||||
@ -708,12 +756,21 @@ static int master_cb(int fd, void *data) {
|
|||||||
cursor_x--;
|
cursor_x--;
|
||||||
terminal_buffer[cursor_y][cursor_x] = ' ';
|
terminal_buffer[cursor_y][cursor_x] = ' ';
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
|
} else if (cursor_y > 0) {
|
||||||
|
cursor_y--;
|
||||||
|
cursor_x = term_cols - 1;
|
||||||
|
while (cursor_x > 0 &&
|
||||||
|
terminal_buffer[cursor_y][cursor_x - 1] == ' ') {
|
||||||
|
cursor_x--;
|
||||||
|
}
|
||||||
|
needs_refresh = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cursor_y < term_rows && cursor_x < term_cols) {
|
if (cursor_y < term_rows && cursor_x < term_cols) {
|
||||||
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;
|
||||||
|
bg_color_buffer[cursor_y][cursor_x] = current_bg_color;
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
cursor_x++;
|
cursor_x++;
|
||||||
if (cursor_x >= term_cols) {
|
if (cursor_x >= term_cols) {
|
||||||
@ -722,7 +779,6 @@ static int master_cb(int fd, void *data) {
|
|||||||
if (cursor_y >= term_rows) {
|
if (cursor_y >= term_rows) {
|
||||||
scroll_up();
|
scroll_up();
|
||||||
cursor_y = term_rows - 1;
|
cursor_y = term_rows - 1;
|
||||||
needs_refresh = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,12 +825,28 @@ static void key_press_cb(XKeyEvent *event, void *data) {
|
|||||||
if (keysym == XK_Return || keysym == XK_KP_Enter) {
|
if (keysym == XK_Return || keysym == XK_KP_Enter) {
|
||||||
write(*master, "\r", 1); // Shell handles return
|
write(*master, "\r", 1); // Shell handles return
|
||||||
} else if (keysym == XK_BackSpace) {
|
} else if (keysym == XK_BackSpace) {
|
||||||
write(*master, "\b", 1); // Shell handles backspace
|
if (cursor_x > 0) {
|
||||||
|
write(*master, "\b \b", 3); // Shell handles backspace
|
||||||
|
} else if (cursor_y > 0) {
|
||||||
|
char seq[8];
|
||||||
|
snprintf(seq, sizeof(seq), "\033[A\033[%dC", term_cols);
|
||||||
|
write(*master, seq, strlen(seq));
|
||||||
|
}
|
||||||
} else if (keysym == XK_Left) {
|
} else if (keysym == XK_Left) {
|
||||||
write(*master, "\033[D", 3);
|
if (cursor_x > 0) {
|
||||||
|
write(*master, "\033[D", 3);
|
||||||
|
} else if (cursor_y > 0) {
|
||||||
|
char seq[8];
|
||||||
|
snprintf(seq, sizeof(seq), "\033[A\033[%dC", term_cols);
|
||||||
|
write(*master, seq, strlen(seq));
|
||||||
|
}
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
} else if (keysym == XK_Right) {
|
} else if (keysym == XK_Right) {
|
||||||
write(*master, "\033[C", 3);
|
if (cursor_x < term_cols - 1) {
|
||||||
|
write(*master, "\033[C", 3);
|
||||||
|
} else if (cursor_y < term_rows - 1) {
|
||||||
|
write(*master, "\033[B\033[G", 6);
|
||||||
|
}
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
} else if (keysym == XK_Up) { // Go up through history
|
} else if (keysym == XK_Up) { // Go up through history
|
||||||
write(*master, "\033[A", 3);
|
write(*master, "\033[A", 3);
|
||||||
@ -786,6 +858,9 @@ static void key_press_cb(XKeyEvent *event, void *data) {
|
|||||||
write(*master, "\t", 1); // Shell handles autocomplete
|
write(*master, "\t", 1); // Shell handles autocomplete
|
||||||
} else if (len > 0) {
|
} else if (len > 0) {
|
||||||
write(*master, buf, len);
|
write(*master, buf, len);
|
||||||
|
if (cursor_x >= term_cols - 1) {
|
||||||
|
write(*master, "\r\n", 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,8 +882,9 @@ int main(void) {
|
|||||||
terminal_buffer = malloc(term_rows * sizeof(char *));
|
terminal_buffer = malloc(term_rows * sizeof(char *));
|
||||||
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
attr_buffer = malloc(term_rows * sizeof(int *));
|
attr_buffer = malloc(term_rows * sizeof(int *));
|
||||||
|
bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
|
||||||
|
|
||||||
if (!terminal_buffer || !color_buffer || !attr_buffer) {
|
if (!terminal_buffer || !color_buffer || !attr_buffer || !bg_color_buffer) {
|
||||||
fprintf(stderr, "Failed to allocate memory for buffers\n");
|
fprintf(stderr, "Failed to allocate memory for buffers\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -817,8 +893,10 @@ int main(void) {
|
|||||||
terminal_buffer[i] = malloc(term_cols * sizeof(char));
|
terminal_buffer[i] = malloc(term_cols * sizeof(char));
|
||||||
color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||||
attr_buffer[i] = malloc(term_cols * sizeof(int));
|
attr_buffer[i] = malloc(term_cols * sizeof(int));
|
||||||
|
bg_color_buffer[i] = malloc(term_cols * sizeof(unsigned long));
|
||||||
|
|
||||||
if (!terminal_buffer[i] || !color_buffer[i] || !attr_buffer[i]) {
|
if (!terminal_buffer[i] || !color_buffer[i] || !attr_buffer[i] ||
|
||||||
|
!bg_color_buffer[i]) {
|
||||||
fprintf(stderr, "Failed to allocate memory for buffer row\n");
|
fprintf(stderr, "Failed to allocate memory for buffer row\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -834,8 +912,15 @@ int main(void) {
|
|||||||
XInitThreads();
|
XInitThreads();
|
||||||
|
|
||||||
current_color = XWhitePixel(display, DefaultScreen(display));
|
current_color = XWhitePixel(display, DefaultScreen(display));
|
||||||
|
current_bg_color = XBlackPixel(display, DefaultScreen(display));
|
||||||
current_attr = 0;
|
current_attr = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < term_rows; y++) {
|
||||||
|
for (int x = 0; x < term_cols; x++) {
|
||||||
|
bg_color_buffer[y][x] = current_bg_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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++) {
|
||||||
color_buffer[y][x] = current_color;
|
color_buffer[y][x] = current_color;
|
||||||
|
Loading…
Reference in New Issue
Block a user