diff options
-rw-r--r-- | math.c | 2 | ||||
-rw-r--r-- | syntax.c | 39 | ||||
-rw-r--r-- | ted.c | 3 | ||||
-rw-r--r-- | text.c | 18 | ||||
-rw-r--r-- | text.h | 2 |
5 files changed, 57 insertions, 7 deletions
@@ -765,7 +765,7 @@ static v4 color_rgba_to_hsva(v4 rgba) { float H = 0; if (C == 0) H = 0; - if (M == R) + else if (M == R) H = fmodf((G - B) / C, 6); else if (M == G) H = (B - R) / C + 2; @@ -1053,6 +1053,7 @@ static void syntax_highlight_javascript(SyntaxState *state, char32_t const *line bool string_is_template = (*state & SYNTAX_STATE_JAVASCRIPT_TEMPLATE_STRING) != 0; bool in_multiline_comment = (*state & SYNTAX_STATE_JAVASCRIPT_MULTILINE_COMMENT) != 0; bool string_is_dbl_quoted = false; + bool string_is_regex = false; bool in_number = false; bool in_string = string_is_template; uint backslashes = 0; @@ -1063,7 +1064,7 @@ static void syntax_highlight_javascript(SyntaxState *state, char32_t const *line switch (c) { case '/': if (!in_string) { - if (i > 0) { + if (i > 0 && in_multiline_comment) { if (line[i-1] == '*') { // end of multi line comment in_multiline_comment = false; @@ -1084,6 +1085,35 @@ static void syntax_highlight_javascript(SyntaxState *state, char32_t const *line dealt_with = true; } } + if (!dealt_with && !in_multiline_comment && !in_string) { + // this is not foolproof for detecting regex literals + // but should handle all "reasonable" uses of regex. + bool is_regex = i == 0 // slash is first char in line + || (line[i-1] <= WCHAR_MAX && iswspace(line[i-1])) // slash preceded by space + || (line[i-1] <= 128 && strchr(";({[=,:", (char)line[i-1])); // slash preceded by any of these characters + if (is_regex) { + in_string = true; + string_is_regex = true; + } + } + } else if (in_string && string_is_regex) { + if (backslashes % 2 == 0) { + // end of regex literal + if (char_types) { + char_types[i] = SYNTAX_STRING; + ++i; + // flags + for (; i < line_len; ++i) { + if (line[i] >= 128 || !strchr("dgimsuy", (char)line[i])) + break; + char_types[i] = SYNTAX_STRING; + } + --i; // back to last char in flags + } + dealt_with = true; + in_string = false; + string_is_regex = false; + } } break; case '\'': @@ -1093,7 +1123,8 @@ static void syntax_highlight_javascript(SyntaxState *state, char32_t const *line bool dbl_quoted = c == '"'; bool template = c == '`'; if (in_string) { - if (string_is_dbl_quoted == dbl_quoted && string_is_template == template && backslashes % 2 == 0) { + if (!string_is_regex && backslashes % 2 == 0 + && string_is_dbl_quoted == dbl_quoted && string_is_template == template) { // end of string in_string = false; if (char_types) char_types[i] = SYNTAX_STRING; @@ -1197,7 +1228,7 @@ static void syntax_highlight_java(SyntaxState *state_ptr, char32_t const *line, in_multiline_comment = true; // /* } } else if (in_multiline_comment) { - if (i > 0 && line[i - 1] == '*') { + if (i > 0 && line[i - 1] == '*' && in_multiline_comment) { // */ in_multiline_comment = false; if (char_types) { @@ -1324,7 +1355,7 @@ static void syntax_highlight_go(SyntaxState *state_ptr, char32_t const *line, u3 in_multiline_comment = true; // /* } } else if (in_multiline_comment) { - if (i > 0 && line[i - 1] == '*') { + if (i > 0 && line[i - 1] == '*' && in_multiline_comment) { // */ in_multiline_comment = false; if (char_types) { @@ -83,6 +83,9 @@ static void ted_load_font(Ted *ted, char const *filename, Font **out) { if (ted_get_file(ted, filename, font_filename, sizeof font_filename)) { Font *font = text_font_load(font_filename, ted->settings.text_size); if (font) { + // we don't properly handle variable-width fonts + text_font_set_force_monospace(font, true); + if (*out) { text_font_free(*out); } @@ -42,6 +42,7 @@ typedef struct { } TextTriangle; struct Font { + bool force_monospace; float char_width; // width of the character 'a'. calculated when font is loaded. float char_height; GLuint textures[CHAR_PAGE_COUNT]; @@ -220,6 +221,10 @@ Font *text_font_load(char const *ttf_filename, float font_size) { return font; } +void text_font_set_force_monospace(Font *font, bool force) { + font->force_monospace = force; +} + float text_font_char_height(Font *font) { return font->char_height; } @@ -280,11 +285,20 @@ top: } stbtt_bakedchar *char_data = font->char_pages[page]; float const char_height = font->char_height; + float const char_width = font->char_width; if (char_data) { // if page was successfully loaded stbtt_aligned_quad q = {0}; state->y += char_height * 0.75f; - stbtt_GetBakedQuad(char_data, font->tex_widths[page], font->tex_heights[page], - (int)index, &state->x, &state->y, &q, 1); + { + float x = state->x, y = state->y; + float *xp = &state->x, *yp = &state->y; + if (font->force_monospace) + xp = &x, yp = &y; + stbtt_GetBakedQuad(char_data, font->tex_widths[page], font->tex_heights[page], + (int)index, xp, yp, &q, 1); + if (font->force_monospace) + state->x += char_width; // ignore actual character width + } state->y -= char_height * 0.75f; float s0 = q.s0, t0 = q.t0; float s1 = q.s1, t1 = q.t1; @@ -49,6 +49,8 @@ extern float text_font_char_height(Font *font); // Width of the character 'a' of this font in pixels. // This is meant to be only used for monospace fonts. extern float text_font_char_width(Font *font); +// Force text to advance by text_font_char_width(font) pixels per character (actually, per code point). +extern void text_font_set_force_monospace(Font *font, bool force); // Get the dimensions of some text. extern void text_get_size(Font *font, char const *text, float *width, float *height); extern v2 text_get_size_v2(Font *font, char const *text); |