From 3f22228a220d065af3f99ba6a538ff80517ecaa2 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 31 Dec 2020 16:35:40 -0500 Subject: configurable colors --- buffer.c | 16 ++++++++++------ colors.c | 36 +++++++++++++++++++++++++----------- config.c | 19 ++++++++++++++++++- main.c | 14 ++++++++++++-- math.c | 7 +++++++ ted-base.c | 5 +---- ted.cfg | 7 +++++++ 7 files changed, 80 insertions(+), 24 deletions(-) diff --git a/buffer.c b/buffer.c index 1c41f92..7d4827d 100644 --- a/buffer.c +++ b/buffer.c @@ -23,6 +23,7 @@ typedef struct BufferEdit { typedef struct { char const *filename; + Settings *settings; double scroll_x, scroll_y; // number of characters scrolled in the x/y direction Font *font; BufferPos cursor_pos; @@ -40,11 +41,12 @@ typedef struct { } TextBuffer; -void buffer_create(TextBuffer *buffer, Font *font) { +void buffer_create(TextBuffer *buffer, Font *font, Settings *settings) { util_zero_memory(buffer, sizeof *buffer); buffer->font = font; buffer->tab_width = 4; buffer->store_undo_events = true; + buffer->settings = settings; } // this is a macro so we get -Wformat warnings @@ -1583,13 +1585,15 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { float char_width = text_font_char_width(font), char_height = text_font_char_height(font); float header_height = char_height; + Settings *settings = buffer->settings; + u32 *colors = settings->colors; // get screen coordinates of cursor v2 cursor_display_pos = buffer_pos_to_pixels(buffer, buffer->cursor_pos); // the rectangle that the cursor is rendered as Rect cursor_rect = rect(cursor_display_pos, V2(1.0f, char_height)); // @SETTINGS: cursor width - u32 border_color = 0x7f7f7fff; // color of border around buffer + u32 border_color = colors[COLOR_BORDER]; // color of border around buffer // bounding box around buffer & header gl_color_rgba(border_color); @@ -1637,7 +1641,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { // highlight line cursor is on { - gl_color1f(0.15f); // @SETTINGS + gl_color_rgba(colors[COLOR_CURSOR_LINE_BG]); glBegin(GL_QUADS); Rect hl_rect = rect(V2(x1, cursor_display_pos.y), V2(x2-x1-1, char_height)); buffer_clip_rect(buffer, &hl_rect); @@ -1655,7 +1659,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { if (buffer->selection) { // draw selection glBegin(GL_QUADS); - gl_color_rgba(0x3366aa88); // @SETTINGS + gl_color_rgba(colors[COLOR_SELECTION_BG]); BufferPos sel_start = {0}, sel_end = {0}; int cmp = buffer_pos_cmp(buffer->cursor_pos, buffer->selection_pos); if (cmp < 0) { @@ -1699,7 +1703,6 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { text_chars_begin(font); - glColor3f(1,1,1); text_state = (TextRenderState){ .x = render_start_x, .y = y1 + text_font_char_height(font), @@ -1709,6 +1712,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { text_state.y -= (float)(buffer->scroll_y - start_line) * char_height; + gl_color_rgba(colors[COLOR_TEXT]); for (u32 line_idx = start_line; line_idx < nlines; ++line_idx) { Line *line = &lines[line_idx]; @@ -1747,7 +1751,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { { // render cursor if (buffer_clip_rect(buffer, &cursor_rect)) { - glColor3f(0,1,1); + gl_color_rgba(colors[COLOR_CURSOR]); glBegin(GL_QUADS); rect_render(cursor_rect); glEnd(); diff --git a/colors.c b/colors.c index d3952c3..297e6d2 100644 --- a/colors.c +++ b/colors.c @@ -7,7 +7,6 @@ ENUM_U16 { COLOR_BORDER, COLOR_TEXT, COLOR_SELECTION_BG, - COLOR_SELECTION_TEXT, COLOR_COUNT } ENUM_U16_END(ColorSetting); @@ -24,8 +23,7 @@ static ColorName const color_names[COLOR_COUNT] = { {COLOR_CURSOR_LINE_BG, "cursor-line-bg"}, {COLOR_BORDER, "border"}, {COLOR_TEXT, "text"}, - {COLOR_SELECTION_BG, "selection-bg"}, - {COLOR_SELECTION_TEXT, "selection-text"} + {COLOR_SELECTION_BG, "selection-bg"} }; static ColorSetting color_setting_from_str(char const *str) { @@ -50,15 +48,31 @@ static char const *color_setting_to_str(ColorSetting s) { // converts #rrggbb/#rrggbbaa to a color. returns false if it's not in the right format. static Status color_from_str(char const *str, u32 *color) { uint r = 0, g = 0, b = 0, a = 0xff; - size_t len = strlen(str); - if (len == 7) { - sscanf(str, "#%02x%02x%02x", &r, &g, &b); - } else if (len == 9) { - sscanf(str, "#%02x%02x%02x%02x", &r, &g, &b, &a); - } else { - return false; + bool success = false; + switch (strlen(str)) { + case 4: + success = sscanf(str, "#%01x%01x%01x", &r, &g, &b) == 3; + // extend single hex digit to double hex digit + r |= r << 4; + g |= g << 4; + b |= b << 4; + break; + case 5: + success = sscanf(str, "#%01x%01x%01x%01x", &r, &g, &b, &a) == 4; + r |= r << 4; + g |= g << 4; + b |= b << 4; + a |= a << 4; + break; + case 7: + success = sscanf(str, "#%02x%02x%02x", &r, &g, &b) == 3; + break; + case 9: + success = sscanf(str, "#%02x%02x%02x%02x", &r, &g, &b, &a) == 4; + break; } - if (r > 0xff || g > 0xff || b > 0xff) return false; + if (!success || r > 0xff || g > 0xff || b > 0xff || a > 0xff) + return false; if (color) *color = (u32)r << 24 | (u32)g << 16 | (u32)b << 8 | (u32)a; return true; diff --git a/config.c b/config.c index 259c85e..eb38cfd 100644 --- a/config.c +++ b/config.c @@ -9,7 +9,8 @@ typedef enum { SECTION_NONE, - SECTION_KEYBOARD + SECTION_KEYBOARD, + SECTION_COLORS } Section; // all worth it for the -Wformat warnings @@ -146,6 +147,7 @@ void config_read(Ted *ted, char const *filename) { .error = false }; ConfigReader *cfg = &cfg_reader; + Settings *settings = &ted->settings; FILE *fp = fopen(filename, "rb"); if (fp) { int line_cap = 4096; @@ -175,6 +177,8 @@ void config_read(Ted *ted, char const *filename) { char *section_name = line + 1; if (streq(section_name, "keyboard")) { section = SECTION_KEYBOARD; + } else if (streq(section_name, "colors")) { + section = SECTION_COLORS; } else { config_err(cfg, "Unrecognized section: [%s].", section_name); } @@ -203,6 +207,19 @@ void config_read(Ted *ted, char const *filename) { config_err(cfg, "Line outside of any section." "Try putting a section header, e.g. [keyboard] before this line?"); break; + case SECTION_COLORS: { + ColorSetting setting = color_setting_from_str(key); + if (setting != COLOR_UNKNOWN) { + u32 color = 0; + if (color_from_str(value, &color)) { + settings->colors[setting] = color; + } else { + config_err(cfg, "'%s' is not a valid color. Colors should look like #rgb, #rgba, #rrggbb, or #rrggbbaa.", value); + } + } else { + config_err(cfg, "No such color option: %s", key); + } + } break; case SECTION_KEYBOARD: { // lines like Ctrl+Down = 10 :down u32 key_combo = config_parse_key_combo(cfg, key); diff --git a/main.c b/main.c index de4f262..dfd78fa 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,9 @@ no_warn_end #include "command.h" #include "util.c" #include "colors.c" +typedef struct { + u32 colors[COLOR_COUNT]; +} Settings; #include "time.c" #include "unicode.h" #define MATH_GL @@ -84,6 +87,8 @@ int main(void) { die("Not enough memory available to run ted."); } + Settings *settings = &ted->settings; + config_read(ted, "ted.cfg"); if (ted_haserr(ted)) { die("Error reading config: %s", ted_geterr(ted)); @@ -91,7 +96,7 @@ int main(void) { TextBuffer text_buffer; TextBuffer *buffer = &text_buffer; - buffer_create(buffer, font); + buffer_create(buffer, font, settings); ted->active_buffer = buffer; if (!buffer_load_file(buffer, "buffer.c")) @@ -198,7 +203,11 @@ int main(void) { glLoadIdentity(); // pixel coordinates; down is positive y glOrtho(0, window_width, window_height, 0, -1, +1); - glClearColor(0, 0, 0, 1); + { // clear (background) + float bg_color[4]; + rgba_u32_to_floats(settings->colors[COLOR_BG], bg_color); + glClearColor(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); + } glClear(GL_COLOR_BUFFER_BIT); { @@ -224,6 +233,7 @@ int main(void) { SDL_Quit(); buffer_free(buffer); text_font_free(font); + free(ted); return 0; } diff --git a/math.c b/math.c index 2909c66..d4adf73 100644 --- a/math.c +++ b/math.c @@ -700,6 +700,13 @@ static void gl_color2f(float v, float a) { glColor4f(v,v,v,a); } +static void rgba_u32_to_floats(u32 rgba, float floats[static 4]) { + floats[0] = (float)(rgba >> 24) / 255.f; + floats[1] = (float)(rgba >> 16) / 255.f; + floats[2] = (float)(rgba >> 8) / 255.f; + floats[3] = (float)(rgba >> 0) / 255.f; +} + // color is 0xRRGGBBAA static void gl_color_rgba(u32 color) { glColor4ub((u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), (u8)color); diff --git a/ted-base.c b/ted-base.c index 8771f02..784bbe9 100644 --- a/ted-base.c +++ b/ted-base.c @@ -4,10 +4,6 @@ typedef struct { i64 argument; } KeyAction; -typedef struct { - u32 colors[COLOR_COUNT]; -} Settings; - #define SCANCODE_COUNT 0x120 // SDL scancodes should be less than this value. // a "key combo" is some subset of {control, shift, alt} + some key. #define KEY_COMBO_COUNT (SCANCODE_COUNT << 3) @@ -21,6 +17,7 @@ typedef struct { typedef struct { TextBuffer *active_buffer; + Settings settings; KeyAction key_actions[KEY_COMBO_COUNT]; char error[256]; } Ted; diff --git a/ted.cfg b/ted.cfg index ba0ffb5..c8b6099 100644 --- a/ted.cfg +++ b/ted.cfg @@ -41,3 +41,10 @@ Ctrl+s = :save Ctrl+z = :undo Ctrl+Shift+z = :redo +[colors] +border = #a77 +cursor-line-bg = #222 +cursor = #3ff +selection-bg = #36a8 +text = #fff +bg = #001 -- cgit v1.2.3