Rewrite of main() and a few other functions

it should have less sloc and better overall
This commit is contained in:
cowmonk 2025-01-20 12:12:07 -07:00
parent 2e81b185e2
commit 9215edb1c1

170
cowterm.c
View File

@ -1107,76 +1107,51 @@ static void key_press_cb(XKeyEvent *event, void *data) {
int main(void) { int main(void) {
int master, slave; int master, slave;
pid_t pid; struct winsize ws = {.ws_row = 24,
.ws_col = 80,
.ws_xpixel = 80 * CHAR_WIDTH,
.ws_ypixel = 24 * CHAR_HEIGHT};
term_rows = ws.ws_row;
term_cols = ws.ws_col;
term_rows = 24; gettimeofday(&last_blink, 0);
term_cols = 80; gettimeofday(&last_refresh, 0);
gettimeofday(&last_blink, NULL); if (!(terminal_buffer = calloc(term_rows, sizeof(char *))) ||
gettimeofday(&last_refresh, NULL); !(color_buffer = calloc(term_rows, sizeof(unsigned long *))) ||
!(attr_buffer = calloc(term_rows, sizeof(int *))) ||
struct winsize ws = {.ws_row = term_rows, !(bg_color_buffer = calloc(term_rows, sizeof(unsigned long *))))
.ws_col = term_cols,
.ws_xpixel = term_cols * CHAR_WIDTH,
.ws_ypixel = term_rows * CHAR_HEIGHT};
terminal_buffer = malloc(term_rows * sizeof(char *));
color_buffer = malloc(term_rows * sizeof(unsigned long *));
attr_buffer = malloc(term_rows * sizeof(int *));
bg_color_buffer = malloc(term_rows * sizeof(unsigned long *));
if (!terminal_buffer || !color_buffer || !attr_buffer || !bg_color_buffer) {
fprintf(stderr, "Failed to allocate memory for buffers\n");
return 1; return 1;
}
for (int i = 0; i < term_rows; i++) { for (int i = 0; i < term_rows; i++) {
terminal_buffer[i] = malloc(term_cols * sizeof(char)); if (!(terminal_buffer[i] = calloc(term_cols, sizeof(char))) ||
color_buffer[i] = malloc(term_cols * sizeof(unsigned long)); !(color_buffer[i] = calloc(term_cols, sizeof(unsigned long))) ||
attr_buffer[i] = malloc(term_cols * sizeof(int)); !(attr_buffer[i] = calloc(term_cols, sizeof(int))) ||
bg_color_buffer[i] = malloc(term_cols * sizeof(unsigned long)); !(bg_color_buffer[i] = calloc(term_cols, sizeof(unsigned long))))
if (!terminal_buffer[i] || !color_buffer[i] || !attr_buffer[i] ||
!bg_color_buffer[i]) {
fprintf(stderr, "Failed to allocate memory for buffer row\n");
return 1; return 1;
}
memset(terminal_buffer[i], ' ', term_cols); memset(terminal_buffer[i], ' ', term_cols);
memset(attr_buffer[i], 0, term_cols * sizeof(int));
} }
display = XOpenDisplay(NULL); if (!(display = XOpenDisplay(0)))
if (!display) {
fprintf(stderr, "Cannot open display\n");
return 1; return 1;
}
XInitThreads(); XInitThreads();
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;
for (int y = 0; y < term_rows; y++) { for (int i = 0; i < term_rows; i++)
for (int x = 0; x < term_cols; x++) { for (int j = 0; j < term_cols; j++) {
bg_color_buffer[y][x] = current_bg_color; bg_color_buffer[i][j] = current_bg_color;
color_buffer[i][j] = current_color;
} }
}
for (int y = 0; y < term_rows; y++) { XSizeHints hints = {.flags = PResizeInc | PMinSize,
for (int x = 0; x < term_cols; x++) { .width_inc = CHAR_WIDTH,
color_buffer[y][x] = current_color; .height_inc = CHAR_HEIGHT,
attr_buffer[y][x] = current_attr; .min_width = CHAR_WIDTH * 4,
} .min_height = CHAR_HEIGHT};
}
XSizeHints hints; Window win = XCreateSimpleWindow(
hints.flags = PResizeInc | PMinSize;
hints.width_inc = CHAR_WIDTH;
hints.height_inc = CHAR_HEIGHT;
hints.min_width = CHAR_WIDTH * 4;
hints.min_height = CHAR_HEIGHT * 1;
Window window = XCreateSimpleWindow(
display, DefaultRootWindow(display), 0, 0, term_cols * CHAR_WIDTH, display, DefaultRootWindow(display), 0, 0, term_cols * CHAR_WIDTH,
term_rows * CHAR_HEIGHT, 0, XBlackPixel(display, DefaultScreen(display)), term_rows * CHAR_HEIGHT, 0, XBlackPixel(display, DefaultScreen(display)),
XBlackPixel(display, DefaultScreen(display))); XBlackPixel(display, DefaultScreen(display)));
@ -1185,76 +1160,66 @@ int main(void) {
term_cols * CHAR_WIDTH, term_rows * CHAR_HEIGHT, term_cols * CHAR_WIDTH, term_rows * CHAR_HEIGHT,
DefaultDepth(display, DefaultScreen(display))); DefaultDepth(display, DefaultScreen(display)));
XSetWMNormalHints(display, window, &hints); XSetWMNormalHints(display, win, &hints);
XStoreName(display, window, window_name); XStoreName(display, win, window_name);
XSelectInput(display, window, XSelectInput(display, win,
KeyPressMask | ExposureMask | StructureNotifyMask | KeyPressMask | ExposureMask | StructureNotifyMask |
FocusChangeMask); FocusChangeMask);
XMapWindow(display, window); XMapWindow(display, win);
if (openpty(&master, &slave, NULL, NULL, &ws) == -1) { if (openpty(&master, &slave, 0, 0, &ws) == -1)
perror("openpty");
return 1; return 1;
}
master_fd = master; master_fd = master;
pid = fork(); if ((child_pid = fork()) == -1)
if (pid < 0) {
perror("fork");
return 1; return 1;
}
if (pid == 0) { if (!child_pid) {
close(master); close(master);
close(STDIN_FILENO); for (int i = 0; i < 3; i++)
close(STDOUT_FILENO); close(i);
close(STDERR_FILENO);
setsid(); setsid();
dup2(slave, 0); for (int i = 0; i < 3; i++)
dup2(slave, 1); if (dup2(slave, i) == -1)
dup2(slave, 2); return 1;
if (slave > 2) if (slave > 2)
close(slave); close(slave);
char *shell = getenv("SHELL"); char *sh = getenv("SHELL");
if (!shell)
shell = "/bin/sh";
setenv("TERM", "xterm-256color", 1); setenv("TERM", "xterm-256color", 1);
execlp(shell, shell, NULL); execl(sh ? sh : "/bin/sh", sh ? sh : "sh", 0);
perror("execlp"); return 1;
exit(1);
} }
child_pid = pid;
close(slave); close(slave);
struct { struct {
Display *display; Display *display;
Window window; Window window;
} ctx = {display, window}; } ctx = {display, win};
XEvent event; XEvent ev;
while (1) { fd_set fds;
int status; struct timeval tv = {0, 1000};
pid_t wpid = waitpid(child_pid, &status, WNOHANG);
if (wpid == child_pid) { for (;;) {
destroy_cb(display, window); if (waitpid(child_pid, 0, WNOHANG) == child_pid) {
destroy_cb(display, win);
return 0; return 0;
} }
while (XPending(display)) { while (XPending(display)) {
XNextEvent(display, &event); XNextEvent(display, &ev);
switch (event.type) { switch (ev.type) {
case ConfigureNotify: { case ConfigureNotify: {
XConfigureEvent *ce = (XConfigureEvent *)&event; XConfigureEvent *ce = &ev.xconfigure;
int new_rows = ce->height / CHAR_HEIGHT; int nr = ce->height / CHAR_HEIGHT;
int new_cols = ce->width / CHAR_WIDTH; int nc = ce->width / CHAR_WIDTH;
if (new_rows != term_rows || new_cols != term_cols) { if (nr != term_rows || nc != term_cols) {
resize_buffers(new_rows, new_cols); resize_buffers(nr, nc);
ws.ws_row = term_rows; ws.ws_row = term_rows;
ws.ws_col = term_cols; ws.ws_col = term_cols;
ws.ws_xpixel = term_cols * CHAR_WIDTH; ws.ws_xpixel = term_cols * CHAR_WIDTH;
@ -1264,34 +1229,29 @@ int main(void) {
break; break;
} }
case FocusIn: case FocusIn:
window_focused = 1; window_focused = needs_refresh = 1;
needs_refresh = 1;
break; break;
case FocusOut: case FocusOut:
window_focused = 0; window_focused = 0;
needs_refresh = 1; needs_refresh = 1;
break; break;
case KeyPress: case KeyPress:
key_press_cb((XKeyEvent *)&event, &master); if (!(ev.xkey.state & ControlMask) && ev.xkey.keycode < 128)
key_press_cb(&ev.xkey, &master);
break; break;
case Expose: case Expose:
needs_refresh = 1; needs_refresh = 1;
check_refresh(display, window); check_refresh(display, win);
break; break;
} }
} }
fd_set fds;
struct timeval tv = {0, 1000}; // 1ms timeout for faster refresh
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(master, &fds); FD_SET(master, &fds);
if (select(master + 1, &fds, NULL, NULL, &tv) > 0) { if (select(master + 1, &fds, 0, 0, &tv) > 0)
master_cb(master, &ctx, window); master_cb(master, &ctx, win);
}
check_refresh(display, window); check_refresh(display, win);
update_cursor_state(display, window); update_cursor_state(display, win);
} }
return 0;
} }