~sircmpwn/scurvy

80ae97eb23c7f6c5745ce22ffe3951d97eaea6da — Drew DeVault 4 years ago 7d9bb6d
Add unicode support
4 files changed, 59 insertions(+), 3 deletions(-)

M CMakeLists.txt
A include/unicode.h
M src/term.c
A src/utf8.c
M CMakeLists.txt => CMakeLists.txt +1 -0
@@ 40,6 40,7 @@ add_executable(scurvy
    src/pango.c
    src/child.c
    src/term.c
    src/utf8.c
)

target_link_libraries(scurvy

A include/unicode.h => include/unicode.h +18 -0
@@ 0,0 1,18 @@
#ifndef _SCURVY_UNICODE_H
#define _SCURVY_UNICODE_H

#include <stddef.h>
#include <stdint.h>

// Technically UTF-8 supports up to 6 byte codepoints, but Unicode itself
// doesn't really bother with more than 4.
#define UTF8_MAX_SIZE 4

#define UTF8_INVALID 0x80

/**
 * Encodes a character as UTF-8 and returns the length of that character.
 */
size_t utf8_encode(char *str, uint32_t ch);

#endif

M src/term.c => src/term.c +10 -3
@@ 1,6 1,7 @@
#include <cairo/cairo.h>
#include <vterm.h>
#include <string.h>
#include "unicode.h"
#include "term.h"
#include "pango.h"
#include "config.h"


@@ 25,15 26,18 @@ void term_render(cairo_t *cairo) {
	int rows, cols;
	vterm_get_size(vterm, &rows, &cols);
	VTermScreenCell cell;
	char buf[VTERM_MAX_CHARS_PER_CELL + 1];
	char buf[VTERM_MAX_CHARS_PER_CELL * 4 + 1];
	int tw, th, _;
	get_text_size(cairo, config->font, &tw, &th, 1, false, "Hello world");
	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);
			memcpy(buf, cell.chars, VTERM_MAX_CHARS_PER_CELL);
			buf[(int)cell.width] = '\0';
			size_t s = 0;
			for (size_t i = 0; cell.chars[i]; ++i) {
				s += utf8_encode(&buf[s], cell.chars[i]);
			}
			buf[s] = '\0';

			get_text_size(cairo, config->font, &tw, &_, 1, false, "%s", buf);
			cairo_set_source_rgb(cairo,


@@ 49,6 53,9 @@ void term_render(cairo_t *cairo) {
					cell.fg.blue / 256.0);
			pango_printf(cairo, config->font, 1, false, "%s", buf);
			x += tw;
			if (cell.width != 1) {
				col += cell.width - 1;
			}
		}
	}
}

A src/utf8.c => src/utf8.c +30 -0
@@ 0,0 1,30 @@
#include <stdint.h>
#include <stddef.h>
#include "unicode.h"

size_t utf8_encode(char *str, uint32_t ch) {
	size_t len = 0;
	uint8_t first;

	if (ch < 0x80) {
		first = 0;
		len = 1;
	} else if (ch < 0x800) {
		first = 0xc0;
		len = 2;
	} else if (ch < 0x10000) {
		first = 0xe0;
		len = 3;
	} else {
		first = 0xf0;
		len = 4;
	}

	for (size_t i = len - 1; i > 0; --i) {
		str[i] = (ch & 0x3f) | 0x80;
		ch >>= 6;
	}

	str[0] = ch | first;
	return len;
}