~sircmpwn/scurvy

07a80e22162ef24e6995519a0f87d1a16f7efe92 — Drew DeVault 4 years ago 80ae97e
Refactor out globals
M include/child.h => include/child.h +3 -1
@@ 1,13 1,15 @@
#ifndef _SCURVY_CHILD_H
#define _SCURVY_CHILD_H
#include <sys/types.h>
#include "term.h"

struct scurvy_child {
	pid_t pid;
	int fd;
	struct scurvy_vterm *term;
};

struct scurvy_child *child_spawn(char **argv);
struct scurvy_child *child_spawn(struct scurvy_vterm *term, char **argv);
void child_free(struct scurvy_child *child);
bool child_read_pty(struct scurvy_child *child);
void child_write_pty(struct scurvy_child *child);

M include/config.h => include/config.h +2 -1
@@ 4,6 4,7 @@
#include <stdbool.h>

struct scurvy_config {
	struct scurvy_vterm *vterm;
	uint32_t background;
	char *font;
	char *url;


@@ 13,6 14,6 @@ struct scurvy_config {

extern struct scurvy_config *config;

bool load_scurvy_config(const char *file);
bool load_scurvy_config(struct scurvy_vterm *term, const char *file);

#endif

M include/term.h => include/term.h +8 -6
@@ 3,12 3,14 @@
#include <vterm.h>
#include <cairo/cairo.h>

extern VTerm *vterm;
extern VTermState *vtstate;
extern VTermScreen *vtscreen;
struct scurvy_vterm {
	VTerm *vterm;
	VTermState *vtstate;
	VTermScreen *vtscreen;
};

void term_init();
void term_render();
void set_term_size(cairo_t *cairo, int width, int height);
struct scurvy_vterm *term_init();
void term_render(struct scurvy_vterm *term, cairo_t *cairo);
void set_term_size(struct scurvy_vterm *term, cairo_t *cairo, int width, int height);

#endif

M include/wayland/window.h => include/wayland/window.h +2 -0
@@ 6,6 6,7 @@
#include <pango/pangocairo.h>
#include <stdbool.h>
#include "wayland/registry.h"
#include "term.h"

struct window;



@@ 50,6 51,7 @@ struct window {
	struct wl_shell_surface *shell_surface;
	struct wl_callback *frame_cb;
	struct cursor cursor;
	struct scurvy_vterm *term;
	uint32_t width, height;
	int32_t scale;
	char *font;

M src/child.c => src/child.c +5 -4
@@ 95,11 95,12 @@ static void init_child(struct scurvy_child *child, char **argv) {
	exit(1);
}

struct scurvy_child *child_spawn(char **argv) {
struct scurvy_child *child_spawn(struct scurvy_vterm *term, char **argv) {
	struct scurvy_child *child = calloc(sizeof(struct scurvy_child), 1);
	if (!child) {
		return NULL;
	}
	child->term = term;
	child->fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
	child->pid = fork();
	if (child->pid < 0) {


@@ 121,8 122,8 @@ bool child_read_pty(struct scurvy_child *child) {
		}
	}
	if (r > 0) {
		vterm_input_write(vterm, buf, r);
		vterm_screen_flush_damage(vtscreen);
		vterm_input_write(child->term->vterm, buf, r);
		vterm_screen_flush_damage(child->term->vtscreen);
		return true;
	}
	return false;


@@ 130,7 131,7 @@ bool child_read_pty(struct scurvy_child *child) {

void child_write_pty(struct scurvy_child *child) {
	static char buf[4096];
	int r = vterm_output_read(vterm, buf, sizeof(buf));
	int r = vterm_output_read(child->term->vterm, buf, sizeof(buf));
	write(child->fd, &buf, r);
}


M src/config.c => src/config.c +9 -7
@@ 65,7 65,7 @@ static bool open_config(const char *path, FILE **f) {
static void set_color(struct scurvy_config *config,
		const char *key, const char *value) {
	VTermColor fg, bg;
	vterm_state_get_default_colors(vtstate, &fg, &bg);
	vterm_state_get_default_colors(config->vterm->vtstate, &fg, &bg);
	uint32_t color;
	if (!color_parse(value, &color)) {
		scurvy_log(L_ERROR, "Invalid color specification '%s'", value);


@@ 83,13 83,13 @@ static void set_color(struct scurvy_config *config,
			scurvy_log(L_ERROR, "Invalid color configuration '%s'", key);
			return;
		}
		vterm_state_set_palette_color(vtstate, index, &col);
		vterm_state_set_palette_color(config->vterm->vtstate, index, &col);
		scurvy_log(L_DEBUG, "Set color%d to %08X", index, color);
	} else if (strcmp(key, "foreground") == 0) {
		vterm_state_set_default_colors(vtstate, &col, &bg);
		vterm_state_set_default_colors(config->vterm->vtstate, &col, &bg);
		scurvy_log(L_DEBUG, "Set foreground to %08X", color);
	} else if (strcmp(key, "background") == 0) {
		vterm_state_set_default_colors(vtstate, &fg, &col);
		vterm_state_set_default_colors(config->vterm->vtstate, &fg, &col);
		config->background = color;
		scurvy_log(L_DEBUG, "Set background to %08X", color);
	} else {


@@ 124,7 124,8 @@ int handle_config_option(void *_config, const char *section,
	return 1;
}

static bool load_config(const char *path, struct scurvy_config *config) {
static bool load_config(const char *path, struct scurvy_vterm *term,
		struct scurvy_config *config) {
	FILE *f;
	if (!open_config(path, &f)) {
		scurvy_log(L_ERROR, "Unable to open %s for reading", path);


@@ 132,6 133,7 @@ static bool load_config(const char *path, struct scurvy_config *config) {
	}

	scurvy_log(L_DEBUG, "Loading config from %s", path);
	config->vterm = term;

	int ini = ini_parse_file(f, handle_config_option, config);
	if (ini != 0) {


@@ 154,7 156,7 @@ void free_config(struct scurvy_config *config) {
	free(config->term);
}

bool load_scurvy_config(const char *file) {
bool load_scurvy_config(struct scurvy_vterm *term, const char *file) {
	static const char *config_paths[] = {
		"$XDG_CONFIG_HOME/scurvy.conf",
	};


@@ 171,7 173,7 @@ bool load_scurvy_config(const char *file) {

	config_defaults(config);

	bool success = load_config(path, config);
	bool success = load_config(path, term, config);

	if (old_config) {
		free_config(old_config);

M src/main.c => src/main.c +7 -7
@@ 5,18 5,18 @@
#include "term.h"
#include "child.h"

int wayland_main(struct scurvy_child *);
int wayland_main(struct scurvy_vterm *term, struct scurvy_child *);

int main(int argc, char **argv) {
	init_log(L_DEBUG);
	term_init();
	if (!load_scurvy_config(NULL)) {
	struct scurvy_vterm *term = term_init();
	if (!load_scurvy_config(term, NULL)) {
		return 1;
	}
	char *_argv[] = { "/usr/bin/sh", "-c", "vim ~/.config/scurvy.conf", NULL };
	struct scurvy_child *child = child_spawn(_argv);
	int status = wayland_main(child);
	char *_argv[] = { "/usr/bin/sh", "-c", "htop", NULL };
	struct scurvy_child *child = child_spawn(term, _argv);
	int status = wayland_main(term, child);
	child_free(child);
	vterm_free(vterm);
	vterm_free(term->vterm);
	return status;
}

M src/term.c => src/term.c +17 -19
@@ 8,10 8,6 @@
#include "child.h"
#include "log.h"

struct VTerm *vterm;
struct VTermState *vtstate;
struct VTermScreen *vtscreen;

void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
	cairo_set_source_rgba(cairo,
			(color >> (3*8) & 0xFF) / 255.0,


@@ 20,11 16,11 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
			(color >> (0*8) & 0xFF) / 255.0);
}

void term_render(cairo_t *cairo) {
void term_render(struct scurvy_vterm *term, cairo_t *cairo) {
	cairo_set_source_u32(cairo, config->background);
	cairo_paint(cairo);
	int rows, cols;
	vterm_get_size(vterm, &rows, &cols);
	vterm_get_size(term->vterm, &rows, &cols);
	VTermScreenCell cell;
	char buf[VTERM_MAX_CHARS_PER_CELL * 4 + 1];
	int tw, th, _;


@@ 32,7 28,7 @@ void term_render(cairo_t *cairo) {
	for (int row = 0; row < rows; ++row) {
		for (int col = 0, x = 0; col < cols; ++col) {
			VTermPos pos = { row, col };
			vterm_screen_get_cell(vtscreen, pos, &cell);
			vterm_screen_get_cell(term->vtscreen, pos, &cell);
			size_t s = 0;
			for (size_t i = 0; cell.chars[i]; ++i) {
				s += utf8_encode(&buf[s], cell.chars[i]);


@@ 60,27 56,29 @@ void term_render(cairo_t *cairo) {
	}
}

void term_init() {
	vterm = vterm_new(24, 80);
	vtstate = vterm_obtain_state(vterm);
	vtscreen = vterm_obtain_screen(vterm);
struct scurvy_vterm *term_init() {
	struct scurvy_vterm *term = calloc(sizeof(struct scurvy_vterm), 1);
	term->vterm = vterm_new(24, 80);
	term->vtstate = vterm_obtain_state(term->vterm);
	term->vtscreen = vterm_obtain_screen(term->vterm);

	vterm_set_utf8(vterm, 1);
	vterm_screen_set_damage_merge(vtscreen, VTERM_DAMAGE_CELL);
	vterm_screen_reset(vtscreen, 1);
	vterm_state_set_bold_highbright(vtstate, true);
	vterm_set_utf8(term->vterm, 1);
	vterm_screen_set_damage_merge(term->vtscreen, VTERM_DAMAGE_CELL);
	vterm_screen_reset(term->vtscreen, 1);
	vterm_state_set_bold_highbright(term->vtstate, true);
	return term;
}

void set_term_size(cairo_t *cairo, int width, int height) {
void set_term_size(struct scurvy_vterm *term, cairo_t *cairo, int width, int height) {
	int rows, cols;
	get_text_size(cairo, config->font, &cols, &rows, 1, false, "H");
	rows = height / rows;
	cols = width / cols;
	int old_rows, old_cols;
	vterm_get_size(vterm, &old_rows, &old_cols);
	vterm_get_size(term->vterm, &old_rows, &old_cols);
	if ((rows && cols) && (old_rows != rows || old_cols != cols)) {
		scurvy_log(L_DEBUG, "Setting size to %d rows %d cols", rows, cols);
		vterm_set_size(vterm, rows, cols);
		vterm_screen_flush_damage(vtscreen);
		vterm_set_size(term->vterm, rows, cols);
		vterm_screen_flush_damage(term->vtscreen);
	}
}

M src/wayland/main.c => src/wayland/main.c +12 -10
@@ 1,3 1,4 @@
#define _POSIX_C_SOURCE 200809L
#include <xkbcommon/xkbcommon.h>
#include <wayland-client.h>
#include <cairo/cairo.h>


@@ 6,6 7,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <time.h>
#include "wayland/window.h"
#include "wayland/registry.h"
#include "config.h"


@@ 13,9 15,6 @@
#include "term.h"
#include "log.h"

struct registry *registry;
struct window *win;

static int term_damage(VTermRect rect, void *data) {
	return 0;
}


@@ 64,8 63,8 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
	.resize = term_resize
};

static void window_resize(struct window *_win) {
	set_term_size(win->cairo, win->width, win->height);
static void window_resize(struct window *win) {
	set_term_size(win->term, win->cairo, win->width, win->height);
}

static void keyboard_event(enum wl_keyboard_key_state state,


@@ 73,20 72,23 @@ static void keyboard_event(enum wl_keyboard_key_state state,
	// TODO
}

int wayland_main(struct scurvy_child *child) {
	vterm_screen_set_callbacks(vtscreen, &vterm_screen_callbacks, child);
	registry = registry_poll();
int wayland_main(struct scurvy_vterm *term, struct scurvy_child *child) {
	vterm_screen_set_callbacks(term->vtscreen, &vterm_screen_callbacks, child);
	struct registry *registry = registry_poll();
	registry->input->notify = keyboard_event;
	win = window_setup(registry, 640, 480, 1, true);
	struct window *win = window_setup(registry, 640, 480, 1, true);
	win->term = term;
	win->notify_resize = window_resize;
	while (wl_display_dispatch(registry->display) != -1) {
		if (window_prerender(win) && win->cairo) {
			child_read_pty(child);
			child_write_pty(child);
			term_render(win->cairo);
			term_render(term, win->cairo);
			window_render(win);
			wl_display_flush(registry->display);
		}
		struct timespec spec = { 0, .5e+8 };
		nanosleep(&spec, NULL);
	}
	window_teardown(win);
	registry_teardown(registry);