diff --git a/xC.c b/xC.c index c628cb4..6f0a7ae 100644 --- a/xC.c +++ b/xC.c @@ -1480,7 +1480,7 @@ struct formatter_item { enum formatter_item_type type : 16; ///< Type of this item int attribute : 16; ///< Attribute ID or a TEXT_* mask - int color; ///< Colour + int color; ///< Colour ([256 << 16] | 16) char *text; ///< String }; @@ -3114,6 +3114,9 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer, union relay_item_data *p = e->items = xcalloc (len * 6, sizeof *e->items); for (struct formatter_item *i = line->items; len--; i++) { + // XXX: See attr_printer_decode_color(), this is a footgun. + int16_t c16 = i->color; + int16_t c256 = i->color >> 16; switch (i->type) { case FORMATTER_ITEM_TEXT: @@ -3125,11 +3128,11 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer, (p++)->kind = RELAY_ITEM_RESET; break; case FORMATTER_ITEM_FG_COLOR: - p->fg_color.color = i->color; + p->fg_color.color = c256 <= 0 ? c16 : c256; (p++)->kind = RELAY_ITEM_FG_COLOR; break; case FORMATTER_ITEM_BG_COLOR: - p->bg_color.color = i->color; + p->bg_color.color = c256 <= 0 ? c16 : c256; (p++)->kind = RELAY_ITEM_BG_COLOR; break; case FORMATTER_ITEM_SIMPLE: diff --git a/xP/public/xP.js b/xP/public/xP.js index 4eebb7a..7517ef8 100644 --- a/xP/public/xP.js +++ b/xP/public/xP.js @@ -1,3 +1,40 @@ +// Copyright (c) 2022, Přemysl Eric Janouch +// SPDX-License-Identifier: 0BSD + +// --- Colours ----------------------------------------------------------------- + +let palette = [ + '#000', '#800', '#080', '#880', '#008', '#808', '#088', '#ccc', + '#888', '#f00', '#0f0', '#ff0', '#00f', '#f0f', '#0ff', '#fff', +] +palette.length = 256 +for (let i = 0; i < 216; i++) { + let r = i / 36 >> 0, g = (i / 6 >> 0) % 6, b = i % 6 + r = !r ? '00' : (55 + 40 * r).toString(16) + g = !g ? '00' : (55 + 40 * g).toString(16) + b = !b ? '00' : (55 + 40 * b).toString(16) + palette[16 + i] = `#${r}${g}${b}` +} +for (let i = 0; i < 24; i++) { + let g = ('0' + (8 + i * 10).toString(16)).slice(-2) + palette[232 + i] = `#${g}${g}${g}` +} + +function applyColor(fg, bg, inverse) { + if (inverse) + [fg, bg] = [bg >= 0 ? bg : 15, fg >= 0 ? fg : 0] + + let style = '' + if (fg >= 0) + style += `color: ${palette[fg]};` + if (bg >= 0) + style += `background-color: ${palette[bg]};` + if (style) + return style +} + +// ---- Event processing ------------------------------------------------------- + // TODO: Probably reset state on disconnect, and indicate to user. let socket = new WebSocket(proxy) @@ -59,6 +96,8 @@ socket.onmessage = function(event) { m.redraw() } +// ---- UI --------------------------------------------------------------------- + let BufferList = { view: vnode => { let items = [] @@ -95,22 +134,33 @@ let Content = { else classes.add(c) } + let fg = -1, bg = -1, inverse = false line.items.forEach(item => { - // TODO: Colours. switch (item.kind) { case 'Text': // TODO: Detect and transform links. content.push(m('span', { class: Array.from(classes.keys()).join(' '), + style: applyColor(fg, bg, inverse), }, item.text)) break case 'Reset': classes.clear() + fg = bg = -1 + inverse = false + break + case 'FgColor': + fg = item.color + break + case 'BgColor': + bg = item.color + break + case 'FlipInverse': + inverse = !inverse break case 'FlipBold': flip('b'); break case 'FlipItalic': flip('i'); break case 'FlipUnderline': flip('u'); break - case 'FlipInverse': flip('i'); break case 'FlipCrossedOut': flip('s'); break case 'FlipMonospace': flip('m'); break }