diff --git a/librz/cons/html.c b/librz/cons/html.c index 0511ced8d8f..b65ce3dae1c 100644 --- a/librz/cons/html.c +++ b/librz/cons/html.c @@ -30,6 +30,20 @@ static const char *gethtmlcolor(const char ptrch) { return ""; } +static const char *gethtmlbrightcolor(const char ptrch) { + switch (ptrch) { + case '0': return "#777"; // Bright Black (Gray) + case '1': return "#ff5555"; // Bright Red + case '2': return "#55ff55"; // Bright Green + case '3': return "#ffff55"; // Bright Yellow + case '4': return "#5555ff"; // Bright Blue + case '5': return "#ff55ff"; // Bright Magenta + case '6': return "#55ffff"; // Bright Cyan + case '7': return "#ffffff"; // Bright White + } + return ""; +} + // TODO: move into rz_util/str RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) { const char *str = ptr; @@ -183,6 +197,14 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) { esc = 0; continue; // invert color + } else if (!strncmp(ptr, "39m", 3)) { + // Reset foreground to default + text_color[0] = '\0'; + need_to_set = true; + ptr += 2; + str = ptr + 1; + esc = 0; + continue; } else if (ptr[0] == '3' && ptr[2] == 'm') { const char *htmlColor = gethtmlcolor(ptr[1]); if (htmlColor) { @@ -193,6 +215,14 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) { str = ptr + 1; esc = 0; continue; + } else if (!strncmp(ptr, "49m", 3)) { + // Reset background to default + background_color[0] = '\0'; + need_to_set = true; + ptr += 2; + str = ptr + 1; + esc = 0; + continue; } else if (ptr[0] == '4' && ptr[2] == 'm') { const char *htmlColor = gethtmlcolor(ptr[1]); if (htmlColor) { @@ -203,6 +233,31 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) { str = ptr + 1; esc = 0; continue; + } else if (ptr[0] == '9' && ptr[2] == 'm') { + const char *htmlColor = gethtmlbrightcolor(ptr[1]); + if (htmlColor) { + rz_str_ncpy(text_color, htmlColor, sizeof(text_color)); + } + need_to_set = true; + ptr = ptr + 2; + str = ptr + 1; + esc = 0; + continue; + } else if (ptr[0] == '1' && + ptr[1] == '0' && + ptr[3] == 'm' && + ptr[2] >= '0' && + ptr[2] <= '7') { + const char *htmlColor = gethtmlbrightcolor(ptr[2]); + if (htmlColor) { + rz_str_ncpy(background_color, htmlColor, + sizeof(background_color)); + } + need_to_set = true; + ptr = ptr + 3; + str = ptr + 1; + esc = 0; + continue; } } } diff --git a/test/unit/test_cons_html.c b/test/unit/test_cons_html.c index 7e27cb8c3ac..930bf7574d6 100644 --- a/test/unit/test_cons_html.c +++ b/test/unit/test_cons_html.c @@ -76,6 +76,82 @@ bool test_cons_to_html() { html = rz_cons_html_filter(Color_RED Color_BGGREEN "aaa" Color_RESET_BG Color_RESET "bbb", NULL); mu_assert_streq_free(html, "aaabbb", "Two different resets opposite order"); + /* Bright foreground colors (90-97) */ + + html = rz_cons_html_filter("\x1b[90mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright black"); + + html = rz_cons_html_filter("\x1b[91mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright red"); + + html = rz_cons_html_filter("\x1b[92mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright green"); + + html = rz_cons_html_filter("\x1b[93mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright yellow"); + + html = rz_cons_html_filter("\x1b[94mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright blue"); + + html = rz_cons_html_filter("\x1b[95mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright magenta"); + + html = rz_cons_html_filter("\x1b[96mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright cyan"); + + html = rz_cons_html_filter("\x1b[97mBright foreground\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright foreground", "Bright white"); + + /* Bright background colors (100-107) */ + + html = rz_cons_html_filter("\x1b[100mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background black"); + + html = rz_cons_html_filter("\x1b[101mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background red"); + + html = rz_cons_html_filter("\x1b[102mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background green"); + + html = rz_cons_html_filter("\x1b[103mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background yellow"); + + html = rz_cons_html_filter("\x1b[104mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background blue"); + + html = rz_cons_html_filter("\x1b[105mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background magenta"); + + html = rz_cons_html_filter("\x1b[106mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background cyan"); + + html = rz_cons_html_filter("\x1b[107mBright background\x1b[0m", NULL); + mu_assert_streq_free(html, "Bright background", "Bright background white"); + + /* Explicit foreground reset (39m) */ + + html = rz_cons_html_filter("\x1b[91mAA\x1b[39mBB", NULL); + mu_assert_streq_free(html, + "AABB", + "Reset bright foreground"); + + html = rz_cons_html_filter("\x1b[91m\x1b[42mAA\x1b[39mBB", NULL); + mu_assert_streq_free(html, + "AA" + "BB", + "Reset foreground preserve background"); + + html = rz_cons_html_filter("\x1b[101mAA\x1b[49mBB", NULL); + mu_assert_streq_free(html, + "AABB", + "Reset bright background"); + + html = rz_cons_html_filter("\x1b[91m\x1b[101mAA\x1b[49mBB", NULL); + mu_assert_streq_free(html, + "AA" + "BB", + "Reset background preserve foreground"); + mu_end; }