summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-07-29 12:18:10 -0400
committerpommicket <pommicket@gmail.com>2022-07-29 12:18:10 -0400
commit8b970f5b47ac14d6e55b0caf5cfe7890ca17d23b (patch)
treed9031142955670a84492448ca88108fac061626c
parentd424dcbfd9586d5cf587e2cfb643e307b9d5e1bd (diff)
fix syntax highlighting and spacing for weird characters
-rw-r--r--math.c2
-rw-r--r--syntax.c39
-rw-r--r--ted.c3
-rw-r--r--text.c18
-rw-r--r--text.h2
5 files changed, 57 insertions, 7 deletions
diff --git a/math.c b/math.c
index 6fa309d..d1f30dc 100644
--- a/math.c
+++ b/math.c
@@ -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;
diff --git a/syntax.c b/syntax.c
index e26560d..9b5c726 100644
--- a/syntax.c
+++ b/syntax.c
@@ -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) {
diff --git a/ted.c b/ted.c
index c5d264b..e98edde 100644
--- a/ted.c
+++ b/ted.c
@@ -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);
}
diff --git a/text.c b/text.c
index cf951e1..cb55e2a 100644
--- a/text.c
+++ b/text.c
@@ -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;
diff --git a/text.h b/text.h
index cfd70e7..b5e6f5a 100644
--- a/text.h
+++ b/text.h
@@ -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);