diff options
| author | frosty <gabriel@bwaaa.monster> | 2026-04-14 18:13:55 -0400 |
|---|---|---|
| committer | frosty <gabriel@bwaaa.monster> | 2026-04-14 18:13:55 -0400 |
| commit | 6738ab0eac3363c33ff74b99dd945444943e3f72 (patch) | |
| tree | 881b89780b2e1474c2193e9999bac6a86f8c168a | |
| parent | 3a99a37b0c1232cf7310f5a5314466839001fec9 (diff) | |
| download | omnisearch-6738ab0eac3363c33ff74b99dd945444943e3f72.tar.gz | |
feat: added colour code preview infobox
| -rw-r--r-- | src/Infobox/ColourCode.c | 166 | ||||
| -rw-r--r-- | src/Infobox/ColourCode.h | 9 | ||||
| -rw-r--r-- | src/Routes/Search.c | 6 |
3 files changed, 181 insertions, 0 deletions
diff --git a/src/Infobox/ColourCode.c b/src/Infobox/ColourCode.c new file mode 100644 index 0000000..7b4d807 --- /dev/null +++ b/src/Infobox/ColourCode.c @@ -0,0 +1,166 @@ +#include "ColourCode.h" +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const unsigned char HEX_VALS[256] = { + ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5, + ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11, + ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15, ['A'] = 10, ['B'] = 11, + ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15, +}; + +static int is_hex_digit(char c) { + return HEX_VALS[(unsigned char)c] || c == '0'; +} + +static int is_valid_hex(const char *s, int len) { + if (len != 3 && len != 6) + return 0; + for (int i = 0; i < len; i++) { + if (!is_hex_digit(s[i])) + return 0; + } + return 1; +} + +static void hex_to_rgb(const char *hex, int *r, int *g, int *b, int len) { + *r = *g = *b = 0; + if (len == 3) { + *r = HEX_VALS[(unsigned char)hex[0]] * 17; + *g = HEX_VALS[(unsigned char)hex[1]] * 17; + *b = HEX_VALS[(unsigned char)hex[2]] * 17; + } else if (len == 6) { + *r = HEX_VALS[(unsigned char)hex[0]] * 16 + HEX_VALS[(unsigned char)hex[1]]; + *g = HEX_VALS[(unsigned char)hex[2]] * 16 + HEX_VALS[(unsigned char)hex[3]]; + *b = HEX_VALS[(unsigned char)hex[4]] * 16 + HEX_VALS[(unsigned char)hex[5]]; + } +} + +static void rgb_to_hsl(int r, int g, int b, int *h, int *s, int *l) { + int max = r > g ? (r > b ? r : b) : (g > b ? g : b); + int min = r < g ? (r < b ? r : b) : (g < b ? g : b); + int delta = max - min; + *l = (max + min) / 2; + *s = 0; + *h = 0; + if (delta > 0) { + *s = (int)((double)delta / (1.0 - fabs(2.0 * *l / 255.0 - 1.0)) * 100.0); + if (max == r) { + *h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0)); + } else if (max == g) { + *h = (int)(60.0 * (((b - r) / delta) + 2.0)); + } else { + *h = (int)(60.0 * (((r - g) / delta) + 4.0)); + } + if (*h < 0) + *h += 360; + } +} + +static void rgb_to_hsv(int r, int g, int b, int *h, int *s, int *v) { + int max = r > g ? (r > b ? r : b) : (g > b ? g : b); + int min = r < g ? (r < b ? r : b) : (g < b ? g : b); + int delta = max - min; + *v = max * 100 / 255; + *s = max > 0 ? delta * 100 / max : 0; + *h = 0; + if (delta > 0) { + if (max == r) { + *h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0)); + } else if (max == g) { + *h = (int)(60.0 * (((b - r) / delta) + 2.0)); + } else { + *h = (int)(60.0 * (((r - g) / delta) + 4.0)); + } + if (*h < 0) + *h += 360; + } +} + +static void rgb_to_cmyk(int r, int g, int b, int *c, int *m, int *y, int *k) { + int max = r > g ? (r > b ? r : b) : (g > b ? g : b); + double kf = 1.0 - max / 255.0; + if (kf >= 0.99) { + *c = *m = *y = *k = 100; + } else { + *c = (int)((1.0 - r / 255.0 - kf) / (1.0 - kf) * 100); + *m = (int)((1.0 - g / 255.0 - kf) / (1.0 - kf) * 100); + *y = (int)((1.0 - b / 255.0 - kf) / (1.0 - kf) * 100); + *k = (int)(kf * 100); + } +} + +int is_colour_code_query(const char *query) { + if (!query) + return 0; + const char *p = query; + if (p[0] == '#') { + p++; + while (*p == ' ') + p++; + const char *end = p; + while (is_hex_digit(*end)) + end++; + int len = end - p; + return is_valid_hex(p, len); + } + return 0; +} + +InfoBox fetch_colour_data(char *query) { + InfoBox info = {NULL, NULL, NULL, NULL}; + if (!query) + return info; + + const char *p = query; + if (p[0] != '#') + return info; + p++; + while (*p == ' ') + p++; + const char *end = p; + while (is_hex_digit(*end)) + end++; + int len = end - p; + if (!is_valid_hex(p, len)) + return info; + + int r, g, b; + hex_to_rgb(p, &r, &g, &b, len); + + int h, s, l; + rgb_to_hsl(r, g, b, &h, &s, &l); + + int h2, s2, v; + rgb_to_hsv(r, g, b, &h2, &s2, &v); + + int c, m, y, k; + rgb_to_cmyk(r, g, b, &c, &m, &y, &k); + + char html[1024]; + snprintf(html, sizeof(html), + "<div class='colour-container' style='line-height: 1.6;'>" + "<div style='display: flex; align-items: flex-start; gap: 16px;'>" + "<div style='width: 100px; height: 100px; border-radius: 12px; " + "border: 1px solid #ddd; background-color: #%.*s; flex-shrink: 0;'></div>" + "<div>" + "<div style='font-size: 1.3em; font-weight: bold; margin-bottom: 8px;'>" + "#%.*s</div>" + "<div style='color: #666; margin-bottom: 4px;'>RGB(%d, %d, %d)</div>" + "<div style='color: #666; margin-bottom: 4px;'>HSL(%d, %d%%, %d%%)</div>" + "<div style='color: #666; margin-bottom: 4px;'>HSV(%d, %d%%, %d%%)</div>" + "<div style='color: #666;'>CMYK(%d%%, %d%%, %d%%, %d%%)</div>" + "</div>" + "</div>" + "</div>", + len, p, len, p, r, g, b, h, s, l, h2, s2, v, c, m, y, k); + + info.title = strdup("Colour"); + info.extract = strdup(html); + info.thumbnail_url = NULL; + info.url = strdup("#"); + + return info; +} diff --git a/src/Infobox/ColourCode.h b/src/Infobox/ColourCode.h new file mode 100644 index 0000000..4fcfabf --- /dev/null +++ b/src/Infobox/ColourCode.h @@ -0,0 +1,9 @@ +#ifndef COLOURCODE_H +#define COLOURCODE_H + +#include "Infobox.h" + +int is_colour_code_query(const char *query); +InfoBox fetch_colour_data(char *query); + +#endif diff --git a/src/Routes/Search.c b/src/Routes/Search.c index f51fc5f..b580c10 100644 --- a/src/Routes/Search.c +++ b/src/Routes/Search.c @@ -1,6 +1,7 @@ #include "Search.h" #include "../Cache/Cache.h" #include "../Infobox/Calculator.h" +#include "../Infobox/ColourCode.h" #include "../Infobox/CurrencyConversion.h" #include "../Infobox/Dictionary.h" #include "../Infobox/UnitConversion.h" @@ -216,11 +217,16 @@ static int is_calculator_query(const char *query) { return 0; } +static InfoBox fetch_colour_wrapper(char *query) { + return fetch_colour_data(query); +} + static InfoBoxHandler handlers[] = { {is_dictionary_query, fetch_dict_wrapper, NULL}, {is_calculator_query, fetch_calc_wrapper, NULL}, {is_unit_conv_query, fetch_unit_wrapper, NULL}, {is_currency_query, fetch_currency_wrapper, NULL}, + {is_colour_code_query, fetch_colour_wrapper, NULL}, {always_true, fetch_wiki_wrapper, construct_wiki_url}, }; enum { HANDLER_COUNT = sizeof(handlers) / sizeof(handlers[0]) }; |
