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