Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add truecolor output mode #104

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/demo/keyboard.c
Expand Up @@ -341,7 +341,7 @@ struct combo func_combos[] = {
{{K_ARROW_RIGHT,0}}
};

void print_tb(const char *str, int x, int y, uint16_t fg, uint16_t bg)
void print_tb(const char *str, int x, int y, uint32_t fg, uint32_t bg)
{
while (*str) {
uint32_t uni;
Expand All @@ -351,7 +351,7 @@ void print_tb(const char *str, int x, int y, uint16_t fg, uint16_t bg)
}
}

void printf_tb(int x, int y, uint16_t fg, uint16_t bg, const char *fmt, ...)
void printf_tb(int x, int y, uint32_t fg, uint32_t bg, const char *fmt, ...)
{
char buf[4096];
va_list vl;
Expand All @@ -361,7 +361,7 @@ void printf_tb(int x, int y, uint16_t fg, uint16_t bg, const char *fmt, ...)
print_tb(buf, x, y, fg, bg);
}

void draw_key(struct key *k, uint16_t fg, uint16_t bg)
void draw_key(struct key *k, uint32_t fg, uint32_t bg)
{
while (k->x) {
tb_change_cell(k->x+2, k->y+4, k->ch, fg, bg);
Expand Down
14 changes: 7 additions & 7 deletions src/demo/output.c
Expand Up @@ -4,7 +4,7 @@

static const char chars[] = "nnnnnnnnnbbbbbbbbbuuuuuuuuuBBBBBBBBB";

static const uint16_t all_attrs[] = {
static const uint32_t all_attrs[] = {
0,
TB_BOLD,
TB_UNDERLINE,
Expand All @@ -18,24 +18,24 @@ static int next_char(int current) {
return current;
}

static void draw_line(int x, int y, uint16_t bg) {
static void draw_line(int x, int y, uint32_t bg) {
int a, c;
int current_char = 0;
for (a = 0; a < 4; a++) {
for (c = TB_DEFAULT; c <= TB_WHITE; c++) {
uint16_t fg = all_attrs[a] | c;
uint32_t fg = all_attrs[a] | c;
tb_change_cell(x, y, chars[current_char], fg, bg);
current_char = next_char(current_char);
x++;
}
}
}

static void print_combinations_table(int sx, int sy, const uint16_t *attrs, int attrs_n) {
static void print_combinations_table(int sx, int sy, const uint32_t *attrs, int attrs_n) {
int i, c;
for (i = 0; i < attrs_n; i++) {
for (c = TB_DEFAULT; c <= TB_WHITE; c++) {
uint16_t bg = attrs[i] | c;
uint32_t bg = attrs[i] | c;
draw_line(sx, sy, bg);
sy++;
}
Expand All @@ -46,8 +46,8 @@ static void draw_all() {
tb_clear();

tb_select_output_mode(TB_OUTPUT_NORMAL);
static const uint16_t col1[] = {0, TB_BOLD};
static const uint16_t col2[] = {TB_REVERSE};
static const uint32_t col1[] = {0, TB_BOLD};
static const uint32_t col2[] = {TB_REVERSE};
print_combinations_table(1, 1, col1, 2);
print_combinations_table(2 + strlen(chars), 1, col2, 1);
tb_present();
Expand Down
14 changes: 7 additions & 7 deletions src/demo/paint.c
Expand Up @@ -18,7 +18,7 @@ static const uint32_t runes[] = {

#define len(a) (sizeof(a)/sizeof(a[0]))

static const uint16_t colors[] = {
static const uint32_t colors[] = {
TB_BLACK,
TB_RED,
TB_GREEN,
Expand All @@ -29,15 +29,15 @@ static const uint16_t colors[] = {
TB_WHITE,
};

void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, void (*attrFunc)(int, uint32_t*, uint16_t*, uint16_t*)) {
void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, void (*attrFunc)(int, uint32_t*, uint32_t*, uint32_t*)) {
int lx = x;
int ly = y;
for (int i = 0; i < n; i++) {
if (lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1) {
*current = i;
}
uint32_t r;
uint16_t fg, bg;
uint32_t fg, bg;
(*attrFunc)(i, &r, &fg, &bg);
tb_change_cell(lx+0, ly+0, r, fg, bg);
tb_change_cell(lx+1, ly+0, r, fg, bg);
Expand All @@ -53,8 +53,8 @@ void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, voi
ly = y;
for (int i = 0; i < n; i++) {
if (*current == i) {
uint16_t fg = TB_RED | TB_BOLD;
uint16_t bg = TB_DEFAULT;
uint32_t fg = TB_RED | TB_BOLD;
uint32_t bg = TB_DEFAULT;
tb_change_cell(lx+0, ly+2, '^', fg, bg);
tb_change_cell(lx+1, ly+2, '^', fg, bg);
tb_change_cell(lx+2, ly+2, '^', fg, bg);
Expand All @@ -64,13 +64,13 @@ void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, voi
}
}

void runeAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
void runeAttrFunc(int i, uint32_t *r, uint32_t *fg, uint32_t *bg) {
*r = runes[i];
*fg = TB_DEFAULT;
*bg = TB_DEFAULT;
}

void colorAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
void colorAttrFunc(int i, uint32_t *r, uint32_t *fg, uint32_t *bg) {
*r = ' ';
*fg = TB_DEFAULT;
*bg = colors[i];
Expand Down
51 changes: 51 additions & 0 deletions src/demo/truecolor.c
@@ -0,0 +1,51 @@
#include "../termbox.h"


int main() {
tb_init();
tb_select_output_mode(TB_OUTPUT_TRUECOLOR);
int w = tb_width();
int h = tb_height();
uint32_t bg = 0x000000, fg = 0x000000;

tb_clear();
int z = 0;

for (int y = 1; y < h; y++) {
for (int x = 1; x < w; x++) {
uint32_t ch;
tb_utf8_char_to_unicode(&ch, "x");
fg = 0;

if (z % 2 == 0) fg |= TB_BOLD;
if (z % 3 == 0) fg |= TB_UNDERLINE;
if (z % 5 == 0) fg |= TB_REVERSE;

tb_change_cell(x, y, ch, fg, bg);
bg += 0x000101;
z++;
}
bg += 0x080000;
if (bg > 0xFFFFFF) {
bg = 0;
}
}

tb_present();

while (1) {
struct tb_event ev;
int t = tb_poll_event(&ev);

if (t == -1) {
break;
}

if (t == TB_EVENT_KEY) {
break;
}
}

tb_shutdown();
return 0;
}
4 changes: 2 additions & 2 deletions src/python/termboxmodule.pyx
Expand Up @@ -28,7 +28,7 @@ cdef extern from "../termbox.h":
void tb_shutdown()
void tb_present()
void tb_clear()
void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
void tb_change_cell(int x, int y, uint32_t ch, uint32_t fg, uint32_t bg)
int tb_width()
int tb_height()
void tb_set_cursor(int x, int y)
Expand Down Expand Up @@ -202,7 +202,7 @@ cdef class Termbox:
tb_present()
pass

def change_cell(self, int x, int y, int ch, uint16_t fg, uint16_t bg):
def change_cell(self, int x, int y, int ch, uint32_t fg, uint32_t bg):
"""Change cell in position (x;y).
"""
tb_change_cell(x, y, ch, fg, bg)
Expand Down
46 changes: 33 additions & 13 deletions src/termbox.c
Expand Up @@ -51,11 +51,11 @@ static int lasty = LAST_COORD_INIT;
static int cursor_x = -1;
static int cursor_y = -1;

static uint16_t background = TB_DEFAULT;
static uint16_t foreground = TB_DEFAULT;
static uint32_t background = TB_DEFAULT;
static uint32_t foreground = TB_DEFAULT;

static void write_cursor(int x, int y);
static void write_sgr(uint16_t fg, uint16_t bg);
static void write_sgr(uint32_t fg, uint32_t bg);

static void cellbuf_init(struct cellbuf *buf, int width, int height);
static void cellbuf_resize(struct cellbuf *buf, int width, int height);
Expand All @@ -64,7 +64,7 @@ static void cellbuf_free(struct cellbuf *buf);

static void update_size(void);
static void update_term_size(void);
static void send_attr(uint16_t fg, uint16_t bg);
static void send_attr(uint32_t fg, uint32_t bg);
static void send_char(int x, int y, uint32_t c);
static void send_clear(void);
static void sigwinch_handler(int xxx);
Expand Down Expand Up @@ -238,7 +238,7 @@ void tb_put_cell(int x, int y, const struct tb_cell *cell)
CELL(&back_buffer, x, y) = *cell;
}

void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
void tb_change_cell(int x, int y, uint32_t ch, uint32_t fg, uint32_t bg)
{
struct tb_cell c = {ch, fg, bg};
tb_put_cell(x, y, &c);
Expand Down Expand Up @@ -345,7 +345,7 @@ int tb_select_output_mode(int mode)
return outputmode;
}

void tb_set_clear_attributes(uint16_t fg, uint16_t bg)
void tb_set_clear_attributes(uint32_t fg, uint32_t bg)
{
foreground = fg;
background = bg;
Expand Down Expand Up @@ -380,13 +380,28 @@ static void write_cursor(int x, int y) {
WRITE_LITERAL("H");
}

static void write_sgr(uint16_t fg, uint16_t bg) {
static void write_sgr(uint32_t fg, uint32_t bg) {
char buf[32];

if (fg == TB_DEFAULT && bg == TB_DEFAULT)
if (outputmode != TB_OUTPUT_TRUECOLOR && fg == TB_DEFAULT && bg == TB_DEFAULT)
return;

switch (outputmode) {
case TB_OUTPUT_TRUECOLOR:
WRITE_LITERAL("\033[38;2;");
WRITE_INT(fg >> 16 & 0xFF);
WRITE_LITERAL(";");
WRITE_INT(fg >> 8 & 0xFF);
WRITE_LITERAL(";");
WRITE_INT(fg & 0xFF);
WRITE_LITERAL(";48;2;");
WRITE_INT(bg >> 16 & 0xFF);
WRITE_LITERAL(";");
WRITE_INT(bg >> 8 & 0xFF);
WRITE_LITERAL(";");
WRITE_INT(bg & 0xFF);
WRITE_LITERAL("m");
break;
case TB_OUTPUT_256:
case TB_OUTPUT_216:
case TB_OUTPUT_GRAYSCALE:
Expand Down Expand Up @@ -495,17 +510,22 @@ static void update_term_size(void)
termh = sz.ws_row;
}

static void send_attr(uint16_t fg, uint16_t bg)
static void send_attr(uint32_t fg, uint32_t bg)
{
#define LAST_ATTR_INIT 0xFFFF
static uint16_t lastfg = LAST_ATTR_INIT, lastbg = LAST_ATTR_INIT;
#define LAST_ATTR_INIT 0xFFFFFFFF
static uint32_t lastfg = LAST_ATTR_INIT, lastbg = LAST_ATTR_INIT;
if (fg != lastfg || bg != lastbg) {
bytebuffer_puts(&output_buffer, funcs[T_SGR0]);

uint16_t fgcol;
uint16_t bgcol;
uint32_t fgcol;
uint32_t bgcol;

switch (outputmode) {
case TB_OUTPUT_TRUECOLOR:
fgcol = fg;
bgcol = bg;
break;

case TB_OUTPUT_256:
fgcol = fg & 0xFF;
bgcol = bg & 0xFF;
Expand Down
18 changes: 11 additions & 7 deletions src/termbox.h
Expand Up @@ -124,9 +124,9 @@ extern "C" {
* combine attributes and a single color. See also struct tb_cell's fg and bg
* fields.
*/
#define TB_BOLD 0x0100
#define TB_UNDERLINE 0x0200
#define TB_REVERSE 0x0400
#define TB_BOLD 0x01000000
#define TB_UNDERLINE 0x02000000
#define TB_REVERSE 0x04000000

/* A cell, single conceptual entity on the terminal screen. The terminal screen
* is basically a 2d array of cells. It has the following fields:
Expand All @@ -136,8 +136,8 @@ extern "C" {
*/
struct tb_cell {
uint32_t ch;
uint16_t fg;
uint16_t bg;
uint32_t fg;
uint32_t bg;
};

#define TB_EVENT_KEY 1
Expand Down Expand Up @@ -194,7 +194,7 @@ SO_IMPORT int tb_height(void);
* color/attributes set by tb_set_clear_attributes() function.
*/
SO_IMPORT void tb_clear(void);
SO_IMPORT void tb_set_clear_attributes(uint16_t fg, uint16_t bg);
SO_IMPORT void tb_set_clear_attributes(uint32_t fg, uint32_t bg);

/* Synchronizes the internal back buffer with the terminal. */
SO_IMPORT void tb_present(void);
Expand All @@ -211,7 +211,7 @@ SO_IMPORT void tb_set_cursor(int cx, int cy);
* position.
*/
SO_IMPORT void tb_put_cell(int x, int y, const struct tb_cell *cell);
SO_IMPORT void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg);
SO_IMPORT void tb_change_cell(int x, int y, uint32_t ch, uint32_t fg, uint32_t bg);

/* Copies the buffer from 'cells' at the specified position, assuming the
* buffer is a two-dimensional array of size ('w' x 'h'), represented as a
Expand Down Expand Up @@ -258,6 +258,7 @@ SO_IMPORT int tb_select_input_mode(int mode);
#define TB_OUTPUT_256 2
#define TB_OUTPUT_216 3
#define TB_OUTPUT_GRAYSCALE 4
#define TB_OUTPUT_TRUECOLOR 5

/* Sets the termbox output mode. Termbox has three output options:
* 1. TB_OUTPUT_NORMAL => [1..8]
Expand Down Expand Up @@ -288,6 +289,9 @@ SO_IMPORT int tb_select_input_mode(int mode);
* This mode supports the 4th range of the 256 mode only.
* But you dont need to provide an offset.
*
* 5. TB_OUTPUT_TRUECOLOR => [0x000000..0xFFFFFF]
* This mode supports 24-bit true color. Format is 0xRRGGBB.
*
* Execute build/src/demo/output to see its impact on your terminal.
*
* If 'mode' is TB_OUTPUT_CURRENT, it returns the current output mode.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome read ❤️

Expand Down