From 0979a0e2e56f196684260e96e2554ebf0b828667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 28 Oct 2019 18:25:19 +0100 Subject: [PATCH] terminal: implement term_init() and term_destroy() --- main.c | 345 +++------------------------------------------------- terminal.c | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++++ terminal.h | 10 ++ 3 files changed, 375 insertions(+), 328 deletions(-) diff --git a/main.c b/main.c index b4e550fa..3d951b67 100644 --- a/main.c +++ b/main.c @@ -330,106 +330,10 @@ main(int argc, char *const *argv) setlocale(LC_ALL, ""); setenv("TERM", conf.term, 1); - struct terminal term = { - .quit = false, - .ptmx = posix_openpt(O_RDWR | O_NOCTTY), - .cursor_keys_mode = CURSOR_KEYS_NORMAL, - .keypad_keys_mode = KEYPAD_NUMERICAL, - .auto_margin = true, - .window_title_stack = tll_init(), - .scale = 1, - .flash = { - .fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK), - }, - .blink = { - .fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK), - }, - .vt = { - .state = 1, /* STATE_GROUND */ - }, - .colors = { - .default_fg = conf.colors.fg, - .default_bg = conf.colors.bg, - .default_table = { - conf.colors.regular[0], - conf.colors.regular[1], - conf.colors.regular[2], - conf.colors.regular[3], - conf.colors.regular[4], - conf.colors.regular[5], - conf.colors.regular[6], - conf.colors.regular[7], - - conf.colors.bright[0], - conf.colors.bright[1], - conf.colors.bright[2], - conf.colors.bright[3], - conf.colors.bright[4], - conf.colors.bright[5], - conf.colors.bright[6], - conf.colors.bright[7], - }, - .alpha = conf.colors.alpha, - }, - .default_cursor_style = conf.cursor.style, - .cursor_style = conf.cursor.style, - .default_cursor_color = { - .text = conf.cursor.color.text, - .cursor = conf.cursor.color.cursor, - }, - .cursor_color = { - .text = conf.cursor.color.text, - .cursor = conf.cursor.color.cursor, - }, - .selection = { - .start = {-1, -1}, - .end = {-1, -1}, - }, - .normal = {.damage = tll_init(), .scroll_damage = tll_init()}, - .alt = {.damage = tll_init(), .scroll_damage = tll_init()}, - .grid = &term.normal, - .render = { - .scrollback_lines = conf.scrollback_lines, - .workers = { - .count = conf.render_worker_count, - .queue = tll_init(), - }, - }, - .delayed_render_timer = { - .is_armed = false, - .lower_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC), - .upper_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC), - }, - }; - - LOG_INFO("using %zu rendering threads", term.render.workers.count); - - struct render_worker_context worker_context[term.render.workers.count]; - - /* Initialize 'current' colors from the default colors */ - term.colors.fg = term.colors.default_fg; - term.colors.bg = term.colors.default_bg; - - /* Initialize the 256 gray-scale color cube */ - { - /* First 16 entries have already been initialized from conf */ - for (size_t r = 0; r < 6; r++) { - for (size_t g = 0; g < 6; g++) { - for (size_t b = 0; b < 6; b++) { - term.colors.default_table[16 + r * 6 * 6 + g * 6 + b] - = r * 51 << 16 | g * 51 << 8 | b * 51; - } - } - } - - for (size_t i = 0; i < 24; i++) - term.colors.default_table[232 + i] = i * 11 << 16 | i * 11 << 8 | i * 11; - - memcpy(term.colors.table, term.colors.default_table, sizeof(term.colors.table)); - } struct fdm *fdm = NULL; struct wayland *wayl = NULL; + struct terminal *term = NULL; if ((fdm = fdm_init()) == NULL) goto out; @@ -437,256 +341,41 @@ main(int argc, char *const *argv) if ((wayl = wayl_init(fdm)) == NULL) goto out; - term.wl = wayl; - wayl->term = &term; - - if (term.ptmx == -1) { - LOG_ERR("failed to open pseudo terminal"); - goto out; - } - - if (term.flash.fd == -1 || term.blink.fd == -1) { - LOG_ERR("failed to create timers"); - goto out; - } - - sem_init(&term.render.workers.start, 0, 0); - sem_init(&term.render.workers.done, 0, 0); - mtx_init(&term.render.workers.lock, mtx_plain); - cnd_init(&term.render.workers.cond); - - term.render.workers.threads = calloc(term.render.workers.count, sizeof(term.render.workers.threads[0])); - for (size_t i = 0; i < term.render.workers.count; i++) { - worker_context[i].term = &term; - worker_context[i].my_id = 1 + i; - thrd_create(&term.render.workers.threads[i], &render_worker_thread, &worker_context[i]); - } - - font_list_t font_names = tll_init(); - tll_foreach(conf.fonts, it) - tll_push_back(font_names, it->item); - - if ((term.fonts[0] = font_from_name(font_names, "")) == NULL) { - tll_free(font_names); - goto out; - } - - term.fonts[1] = font_from_name(font_names, "style=bold"); - term.fonts[2] = font_from_name(font_names, "style=italic"); - term.fonts[3] = font_from_name(font_names, "style=bold italic"); - - tll_free(font_names); - - { - FT_Face ft_face = term.fonts[0]->face; - int max_x_advance = ft_face->size->metrics.max_advance / 64; - int height = ft_face->size->metrics.height / 64; - int descent = ft_face->size->metrics.descender / 64; - int ascent = ft_face->size->metrics.ascender / 64; - - term.fextents.height = height * term.fonts[0]->pixel_size_fixup; - term.fextents.descent = -descent * term.fonts[0]->pixel_size_fixup; - term.fextents.ascent = ascent * term.fonts[0]->pixel_size_fixup; - term.fextents.max_x_advance = max_x_advance * term.fonts[0]->pixel_size_fixup; - - LOG_DBG("metrics: height: %d, descent: %d, ascent: %d, x-advance: %d", - height, descent, ascent, max_x_advance); - } - - term.cell_width = (int)ceil(term.fextents.max_x_advance); - term.cell_height = (int)ceil(term.fextents.height); - LOG_INFO("cell width=%d, height=%d", term.cell_width, term.cell_height); - - /* Main window */ - term.window = wayl_win_init(wayl); - if (term.window == NULL) + if ((term = term_init(&conf, fdm, wayl, argc, argv)) == NULL) goto out; - term_set_window_title(&term, "foot"); - - if (conf.width == -1) { - assert(conf.height == -1); - conf.width = 80 * term.cell_width; - conf.height = 24 * term.cell_height; - } - - conf.width = max(conf.width, term.cell_width); - conf.height = max(conf.height, term.cell_height); - render_resize(&term, conf.width, conf.height); - - { - int fork_pipe[2]; - if (pipe2(fork_pipe, O_CLOEXEC) < 0) { - LOG_ERRNO("failed to create pipe"); - goto out; - } - - term.slave = fork(); - switch (term.slave) { - case -1: - LOG_ERRNO("failed to fork"); - close(fork_pipe[0]); - close(fork_pipe[1]); - goto out; - - case 0: - /* Child */ - close(fork_pipe[0]); /* Close read end */ - - char **_shell_argv = NULL; - char *const *shell_argv = argv; - - if (argc == 0) { - if (!tokenize_cmdline(conf.shell, &_shell_argv)) { - (void)!write(fork_pipe[1], &errno, sizeof(errno)); - _exit(0); - } - shell_argv = _shell_argv; - } - - slave_spawn(term.ptmx, shell_argv, fork_pipe[1]); - assert(false); - break; - - default: { - close(fork_pipe[1]); /* Close write end */ - LOG_DBG("slave has PID %d", term.slave); - - int _errno; - static_assert(sizeof(errno) == sizeof(_errno), "errno size mismatch"); - - ssize_t ret = read(fork_pipe[0], &_errno, sizeof(_errno)); - close(fork_pipe[0]); - - if (ret < 0) { - LOG_ERRNO("failed to read from pipe"); - goto out; - } else if (ret == sizeof(_errno)) { - LOG_ERRNO( - "%s: failed to execute", argc == 0 ? conf.shell : argv[0]); - goto out; - } else - LOG_DBG("%s: successfully started", conf.shell); - break; - } - } - } - - /* Read logic requires non-blocking mode */ - { - int fd_flags = fcntl(term.ptmx, F_GETFL); - if (fd_flags == -1) { - LOG_ERRNO("failed to set non blocking mode on PTY master"); - goto out; - } - - if (fcntl(term.ptmx, F_SETFL, fd_flags | O_NONBLOCK) == -1) { - LOG_ERRNO("failed to set non blocking mode on PTY master"); - goto out; - } - } - - fdm_add(fdm, term.ptmx, EPOLLIN, &fdm_ptmx, &term); - fdm_add(fdm, term.flash.fd, EPOLLIN, &fdm_flash, &term); - fdm_add(fdm, term.blink.fd, EPOLLIN, &fdm_blink, &term); - fdm_add(fdm, term.delayed_render_timer.lower_fd, EPOLLIN, &fdm_delayed_render, &term); - fdm_add(fdm, term.delayed_render_timer.upper_fd, EPOLLIN, &fdm_delayed_render, &term); + fdm_add(fdm, term->ptmx, EPOLLIN, &fdm_ptmx, term); + fdm_add(fdm, term->flash.fd, EPOLLIN, &fdm_flash, term); + fdm_add(fdm, term->blink.fd, EPOLLIN, &fdm_blink, term); + fdm_add(fdm, term->delayed_render_timer.lower_fd, EPOLLIN, &fdm_delayed_render, term); + fdm_add(fdm, term->delayed_render_timer.upper_fd, EPOLLIN, &fdm_delayed_render, term); while (true) { - wl_display_flush(term.wl->display); /* TODO: figure out how to get rid of this */ + wl_display_flush(term->wl->display); /* TODO: figure out how to get rid of this */ if (!fdm_poll(fdm)) break; } - if (term.quit) + if (term->quit) ret = EXIT_SUCCESS; out: if (fdm != NULL) { - fdm_del(fdm, term.ptmx); - fdm_del(fdm, term.flash.fd); - fdm_del(fdm, term.blink.fd); - fdm_del(fdm, term.delayed_render_timer.lower_fd); - fdm_del(fdm, term.delayed_render_timer.upper_fd); + fdm_del(fdm, term->ptmx); + fdm_del(fdm, term->flash.fd); + fdm_del(fdm, term->blink.fd); + fdm_del(fdm, term->delayed_render_timer.lower_fd); + fdm_del(fdm, term->delayed_render_timer.upper_fd); } - if (term.delayed_render_timer.lower_fd != -1) - close(term.delayed_render_timer.lower_fd); - if (term.delayed_render_timer.upper_fd != -1) - close(term.delayed_render_timer.upper_fd); - - mtx_lock(&term.render.workers.lock); - assert(tll_length(term.render.workers.queue) == 0); - for (size_t i = 0; i < term.render.workers.count; i++) { - sem_post(&term.render.workers.start); - tll_push_back(term.render.workers.queue, -2); - } - cnd_broadcast(&term.render.workers.cond); - mtx_unlock(&term.render.workers.lock); - shm_fini(); - wayl_win_destroy(term.window); + int child_ret = term_destroy(term); wayl_destroy(wayl); - - free(term.vt.osc.data); - for (int row = 0; row < term.normal.num_rows; row++) - grid_row_free(term.normal.rows[row]); - free(term.normal.rows); - for (int row = 0; row < term.alt.num_rows; row++) - grid_row_free(term.alt.rows[row]); - free(term.alt.rows); - - free(term.window_title); - tll_free_and_free(term.window_title_stack, free); - - for (size_t i = 0; i < sizeof(term.fonts) / sizeof(term.fonts[0]); i++) - font_destroy(term.fonts[i]); - - free(term.search.buf); - - if (term.flash.fd != -1) - close(term.flash.fd); - if (term.blink.fd != -1) - close(term.blink.fd); - - if (term.ptmx != -1) - close(term.ptmx); - - for (size_t i = 0; i < term.render.workers.count; i++) - thrd_join(term.render.workers.threads[i], NULL); - free(term.render.workers.threads); - cnd_destroy(&term.render.workers.cond); - mtx_destroy(&term.render.workers.lock); - sem_destroy(&term.render.workers.start); - sem_destroy(&term.render.workers.done); - assert(tll_length(term.render.workers.queue) == 0); - tll_free(term.render.workers.queue); - - if (term.slave > 0) { - /* Note: we've closed ptmx, so the slave *should* exit... */ - int status; - waitpid(term.slave, &status, 0); - - int child_ret = EXIT_FAILURE; - if (WIFEXITED(status)) { - child_ret = WEXITSTATUS(status); - LOG_DBG("slave exited with code %d", child_ret); - } else if (WIFSIGNALED(status)) { - child_ret = WTERMSIG(status); - LOG_WARN("slave exited with signal %d", child_ret); - } else { - LOG_WARN("slave exited for unknown reason (status = 0x%08x)", status); - } - - if (ret == EXIT_SUCCESS) - ret = child_ret; - } - fdm_destroy(fdm); - config_free(conf); - return ret; + + return ret == EXIT_SUCCESS ? child_ret : ret; } diff --git a/terminal.c b/terminal.c index 684f4c30..023390d9 100644 --- a/terminal.c +++ b/terminal.c @@ -3,8 +3,12 @@ #include #include #include +#include +#include +#include #include +#include #include #define LOG_MODULE "terminal" @@ -14,10 +18,354 @@ #include "render.h" #include "vt.h" #include "selection.h" +#include "config.h" +#include "tokenize.h" +#include "slave.h" #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) +struct terminal * +term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, + int argc, char *const *argv) +{ + struct terminal *term = malloc(sizeof(*term)); + *term = (struct terminal) { + .fdm = fdm, + .quit = false, + .ptmx = posix_openpt(O_RDWR | O_NOCTTY), + .cursor_keys_mode = CURSOR_KEYS_NORMAL, + .keypad_keys_mode = KEYPAD_NUMERICAL, + .auto_margin = true, + .window_title_stack = tll_init(), + .scale = 1, + .flash = { + .fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK), + }, + .blink = { + .fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK), + }, + .vt = { + .state = 1, /* STATE_GROUND */ + }, + .colors = { + .default_fg = conf->colors.fg, + .default_bg = conf->colors.bg, + .default_table = { + conf->colors.regular[0], + conf->colors.regular[1], + conf->colors.regular[2], + conf->colors.regular[3], + conf->colors.regular[4], + conf->colors.regular[5], + conf->colors.regular[6], + conf->colors.regular[7], + + conf->colors.bright[0], + conf->colors.bright[1], + conf->colors.bright[2], + conf->colors.bright[3], + conf->colors.bright[4], + conf->colors.bright[5], + conf->colors.bright[6], + conf->colors.bright[7], + }, + .alpha = conf->colors.alpha, + }, + .default_cursor_style = conf->cursor.style, + .cursor_style = conf->cursor.style, + .default_cursor_color = { + .text = conf->cursor.color.text, + .cursor = conf->cursor.color.cursor, + }, + .cursor_color = { + .text = conf->cursor.color.text, + .cursor = conf->cursor.color.cursor, + }, + .selection = { + .start = {-1, -1}, + .end = {-1, -1}, + }, + .normal = {.damage = tll_init(), .scroll_damage = tll_init()}, + .alt = {.damage = tll_init(), .scroll_damage = tll_init()}, + .grid = &term->normal, + .wl = wayl, + .render = { + .scrollback_lines = conf->scrollback_lines, + .workers = { + .count = conf->render_worker_count, + .queue = tll_init(), + }, + }, + .delayed_render_timer = { + .is_armed = false, + .lower_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC), + .upper_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC), + }, + }; + + LOG_INFO("using %zu rendering threads", term->render.workers.count); + + struct render_worker_context worker_context[term->render.workers.count]; + + /* Initialize 'current' colors from the default colors */ + term->colors.fg = term->colors.default_fg; + term->colors.bg = term->colors.default_bg; + + /* Initialize the 256 gray-scale color cube */ + { + /* First 16 entries have already been initialized from conf */ + for (size_t r = 0; r < 6; r++) { + for (size_t g = 0; g < 6; g++) { + for (size_t b = 0; b < 6; b++) { + term->colors.default_table[16 + r * 6 * 6 + g * 6 + b] + = r * 51 << 16 | g * 51 << 8 | b * 51; + } + } + } + + for (size_t i = 0; i < 24; i++) + term->colors.default_table[232 + i] = i * 11 << 16 | i * 11 << 8 | i * 11; + + memcpy(term->colors.table, term->colors.default_table, sizeof(term->colors.table)); + } + if (term->ptmx == -1) { + LOG_ERR("failed to open pseudo terminal"); + goto out; + } + + if (term->flash.fd == -1 || term->blink.fd == -1) { + LOG_ERR("failed to create timers"); + goto out; + } + + sem_init(&term->render.workers.start, 0, 0); + sem_init(&term->render.workers.done, 0, 0); + mtx_init(&term->render.workers.lock, mtx_plain); + cnd_init(&term->render.workers.cond); + + term->render.workers.threads = calloc(term->render.workers.count, sizeof(term->render.workers.threads[0])); + for (size_t i = 0; i < term->render.workers.count; i++) { + worker_context[i].term = term; + worker_context[i].my_id = 1 + i; + thrd_create(&term->render.workers.threads[i], &render_worker_thread, &worker_context[i]); + } + + font_list_t font_names = tll_init(); + tll_foreach(conf->fonts, it) + tll_push_back(font_names, it->item); + + if ((term->fonts[0] = font_from_name(font_names, "")) == NULL) { + tll_free(font_names); + goto out; + } + + term->fonts[1] = font_from_name(font_names, "style=bold"); + term->fonts[2] = font_from_name(font_names, "style=italic"); + term->fonts[3] = font_from_name(font_names, "style=bold italic"); + + tll_free(font_names); + + { + FT_Face ft_face = term->fonts[0]->face; + int max_x_advance = ft_face->size->metrics.max_advance / 64; + int height = ft_face->size->metrics.height / 64; + int descent = ft_face->size->metrics.descender / 64; + int ascent = ft_face->size->metrics.ascender / 64; + + term->fextents.height = height * term->fonts[0]->pixel_size_fixup; + term->fextents.descent = -descent * term->fonts[0]->pixel_size_fixup; + term->fextents.ascent = ascent * term->fonts[0]->pixel_size_fixup; + term->fextents.max_x_advance = max_x_advance * term->fonts[0]->pixel_size_fixup; + + LOG_DBG("metrics: height: %d, descent: %d, ascent: %d, x-advance: %d", + height, descent, ascent, max_x_advance); + } + + term->cell_width = (int)ceil(term->fextents.max_x_advance); + term->cell_height = (int)ceil(term->fextents.height); + LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height); + + /* Main window */ + term->window = wayl_win_init(wayl); + if (term->window == NULL) + goto out; + + term_set_window_title(term, "foot"); + + unsigned width = conf->width; + unsigned height = conf->height; + + if (width == -1) { + assert(height == -1); + width = 80 * term->cell_width; + height = 24 * term->cell_height; + } + + width = max(width, term->cell_width); + height = max(height, term->cell_height); + render_resize(term, width, height); + + { + int fork_pipe[2]; + if (pipe2(fork_pipe, O_CLOEXEC) < 0) { + LOG_ERRNO("failed to create pipe"); + goto out; + } + + term->slave = fork(); + switch (term->slave) { + case -1: + LOG_ERRNO("failed to fork"); + close(fork_pipe[0]); + close(fork_pipe[1]); + goto out; + + case 0: + /* Child */ + close(fork_pipe[0]); /* Close read end */ + + char **_shell_argv = NULL; + char *const *shell_argv = argv; + + if (argc == 0) { + if (!tokenize_cmdline(conf->shell, &_shell_argv)) { + (void)!write(fork_pipe[1], &errno, sizeof(errno)); + _exit(0); + } + shell_argv = _shell_argv; + } + + slave_spawn(term->ptmx, shell_argv, fork_pipe[1]); + assert(false); + break; + + default: { + close(fork_pipe[1]); /* Close write end */ + LOG_DBG("slave has PID %d", term->slave); + + int _errno; + static_assert(sizeof(errno) == sizeof(_errno), "errno size mismatch"); + + ssize_t ret = read(fork_pipe[0], &_errno, sizeof(_errno)); + close(fork_pipe[0]); + + if (ret < 0) { + LOG_ERRNO("failed to read from pipe"); + goto out; + } else if (ret == sizeof(_errno)) { + LOG_ERRNO( + "%s: failed to execute", argc == 0 ? conf->shell : argv[0]); + goto out; + } else + LOG_DBG("%s: successfully started", conf->shell); + break; + } + } + } + + /* Read logic requires non-blocking mode */ + { + int fd_flags = fcntl(term->ptmx, F_GETFL); + if (fd_flags == -1) { + LOG_ERRNO("failed to set non blocking mode on PTY master"); + goto out; + } + + if (fcntl(term->ptmx, F_SETFL, fd_flags | O_NONBLOCK) == -1) { + LOG_ERRNO("failed to set non blocking mode on PTY master"); + goto out; + } + } + + wayl->term = term; + return term; + +out: + term_destroy(term); + return NULL; +} + +int +term_destroy(struct terminal *term) +{ + if (term == NULL) + return 0; + + wayl_win_destroy(term->window); + + if (term->delayed_render_timer.lower_fd != -1) + close(term->delayed_render_timer.lower_fd); + if (term->delayed_render_timer.upper_fd != -1) + close(term->delayed_render_timer.upper_fd); + + mtx_lock(&term->render.workers.lock); + assert(tll_length(term->render.workers.queue) == 0); + for (size_t i = 0; i < term->render.workers.count; i++) { + sem_post(&term->render.workers.start); + tll_push_back(term->render.workers.queue, -2); + } + cnd_broadcast(&term->render.workers.cond); + mtx_unlock(&term->render.workers.lock); + free(term->vt.osc.data); + for (int row = 0; row < term->normal.num_rows; row++) + grid_row_free(term->normal.rows[row]); + free(term->normal.rows); + for (int row = 0; row < term->alt.num_rows; row++) + grid_row_free(term->alt.rows[row]); + free(term->alt.rows); + + free(term->window_title); + tll_free_and_free(term->window_title_stack, free); + + for (size_t i = 0; i < sizeof(term->fonts) / sizeof(term->fonts[0]); i++) + font_destroy(term->fonts[i]); + + free(term->search.buf); + + if (term->flash.fd != -1) + close(term->flash.fd); + if (term->blink.fd != -1) + close(term->blink.fd); + + if (term->ptmx != -1) + close(term->ptmx); + + for (size_t i = 0; i < term->render.workers.count; i++) + thrd_join(term->render.workers.threads[i], NULL); + free(term->render.workers.threads); + cnd_destroy(&term->render.workers.cond); + mtx_destroy(&term->render.workers.lock); + sem_destroy(&term->render.workers.start); + sem_destroy(&term->render.workers.done); + assert(tll_length(term->render.workers.queue) == 0); + tll_free(term->render.workers.queue); + + int ret = EXIT_SUCCESS; + + if (term->slave > 0) { + /* Note: we've closed ptmx, so the slave *should* exit... */ + int status; + waitpid(term->slave, &status, 0); + + int child_ret = EXIT_FAILURE; + if (WIFEXITED(status)) { + child_ret = WEXITSTATUS(status); + LOG_DBG("slave exited with code %d", child_ret); + } else if (WIFSIGNALED(status)) { + child_ret = WTERMSIG(status); + LOG_WARN("slave exited with signal %d", child_ret); + } else { + LOG_WARN("slave exited for unknown reason (status = 0x%08x)", status); + } + + ret = child_ret; + } + + free(term); + return ret; +} + void term_reset(struct terminal *term, bool hard) { diff --git a/terminal.h b/terminal.h index 2f3fcdc5..7303f503 100644 --- a/terminal.h +++ b/terminal.h @@ -8,6 +8,8 @@ #include #include +//#include "config.h" +#include "fdm.h" #include "font.h" #include "tllist.h" #include "wayland.h" @@ -142,6 +144,8 @@ enum mouse_reporting { enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR }; struct terminal { + struct fdm *fdm; + pid_t slave; int ptmx; bool quit; @@ -283,6 +287,12 @@ struct terminal { } delayed_render_timer; }; +struct config; +struct terminal *term_init( + const struct config *conf, struct fdm *fdm, struct wayland *wayl, + int argc, char *const *argv); +int term_destroy(struct terminal *term); + void term_reset(struct terminal *term, bool hard); void term_damage_rows(struct terminal *term, int start, int end);