diff options
-rw-r--r-- | html.c | 79 |
1 files changed, 75 insertions, 4 deletions
diff --git a/html.c b/html.c index ae4c76f..1d2cec0 100644 --- a/html.c +++ b/html.c @@ -15,9 +15,11 @@ */ #include <assert.h> +#include <ctype.h> #include <err.h> #include <inttypes.h> #include <regex.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -422,9 +424,78 @@ enum kcgi_err linkify(struct khtmlreq *html, const char *str, size_t len) { return KCGI_OK; } +static const struct Style { + int fg, bg; + bool b, r, i, u; +} Default = { .fg = 99, .bg = 99 }; + +enum kcgi_err htmlStyle(struct khtmlreq *html, struct Style style) { + enum kcgi_err error = KCGI_OK; + char class[sizeof("fg99")]; + if (style.fg != Default.fg) { + snprintf(class, sizeof(class), "fg%02d", style.fg); + error = error || khtml_attr( + html, KELEM_SPAN, + KATTR_CLASS, class, + KATTR__MAX + ); + } + if (style.bg != Default.bg) { + snprintf(class, sizeof(class), "bg%02d", style.bg); + error = error || khtml_attr( + html, KELEM_SPAN, + KATTR_CLASS, class, + KATTR__MAX + ); + } + if (style.b) error = error || khtml_elem(html, KELEM_B); + if (style.r) error = error || khtml_elem(html, KELEM_MARK); + if (style.i) error = error || khtml_elem(html, KELEM_I); + if (style.u) error = error || khtml_elem(html, KELEM_U); + return error; +} + enum kcgi_err htmlIRC(struct khtmlreq *html, const char *str) { - return 0 - || khtml_attr(html, KELEM_SPAN, KATTR_CLASS, "irc", KATTR__MAX) - || linkify(html, str, strlen(str)) - || khtml_closeelem(html, 1); + enum kcgi_err error = khtml_attr( + html, KELEM_SPAN, + KATTR_CLASS, "irc", + KATTR__MAX + ); + if (error) return error; + + size_t top = khtml_elemat(html); + struct Style style = Default; + for (;;) { + size_t len = strcspn(str, "\2\3\17\26\35\37"); + if (len) { + error = 0 + || khtml_closeto(html, top) + || htmlStyle(html, style) + || linkify(html, str, len); + if (error) return error; + } + + str += len; + if (!*str) break; + switch (*str++) { + break; case '\2': style.b ^= true; + break; case '\26': style.r ^= true; + break; case '\35': style.i ^= true; + break; case '\37': style.u ^= true; + break; case '\3': { + if (!isdigit(*str)) { + style.fg = Default.fg; + style.bg = Default.bg; + break; + } + style.fg = *str++ - '0'; + if (isdigit(*str)) style.fg = style.fg * 10 + *str++ - '0'; + if (str[0] != ',' || !isdigit(str[1])) break; + str++; + style.bg = *str++ - '0'; + if (isdigit(*str)) style.bg = style.bg * 10 + *str++ - '0'; + } + } + } + return khtml_closeto(html, top) || khtml_closeelem(html, 1); } |