From adf918520976a5f06181c1c05392a0da6e4bbaa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Mon, 23 Nov 2020 20:12:11 +0100 Subject: [PATCH] Fully support non-ascii characters in Meter-Bar Currently the code does not handle multi-byte characters, so length- computations take the raw count of C characters and not the to displayed size into account. An example is the degree sign for temperatures. Closes: #329 --- Meter.c | 25 +++++++++++++++++-------- RichString.c | 9 +++++++++ RichString.h | 2 ++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Meter.c b/Meter.c index cf8ccc52..2f02f0ad 100644 --- a/Meter.c +++ b/Meter.c @@ -196,12 +196,19 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) { attrset(CRT_colors[RESET_COLOR]); return; } - char bar[w + 1]; + + // The text in the bar is right aligned; + // calculate needed padding and generate leading spaces + const int textLen = mbstowcs(NULL, buffer, 0); + const int padding = MAXIMUM(w - textLen, 0); + + RichString_begin(bar); + RichString_appendChr(&bar, ' ', padding); + RichString_append(&bar, 0, buffer); + assert(RichString_sizeVal(bar) >= w); int blockSizes[10]; - xSnprintf(bar, w + 1, "%*.*s", w, w, buffer); - // First draw in the bar[] buffer... int offset = 0; for (uint8_t i = 0; i < this->curItems; i++) { @@ -216,11 +223,11 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) { // (Control against invalid values) nextOffset = CLAMP(nextOffset, 0, w); for (int j = offset; j < nextOffset; j++) - if (bar[j] == ' ') { + if (RichString_getCharVal(bar, j) == ' ') { if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { - bar[j] = BarMeterMode_characters[i]; + RichString_setChar(&bar, j, BarMeterMode_characters[i]); } else { - bar[j] = '|'; + RichString_setChar(&bar, j, '|'); } } offset = nextOffset; @@ -230,15 +237,17 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) { offset = 0; for (uint8_t i = 0; i < this->curItems; i++) { attrset(CRT_colors[Meter_attributes(this)[i]]); - mvaddnstr(y, x + offset, bar + offset, blockSizes[i]); + RichString_printoffnVal(bar, y, x + offset, offset, blockSizes[i]); offset += blockSizes[i]; offset = CLAMP(offset, 0, w); } if (offset < w) { attrset(CRT_colors[BAR_SHADOW]); - mvaddnstr(y, x + offset, bar + offset, w - offset); + RichString_printoffnVal(bar, y, x + offset, offset, w - offset); } + RichString_end(bar); + move(y, x + w + 1); attrset(CRT_colors[RESET_COLOR]); } diff --git a/RichString.c b/RichString.c index 904b44b6..1d2a3fee 100644 --- a/RichString.c +++ b/RichString.c @@ -119,6 +119,15 @@ void RichString_prune(RichString* this) { this->chptr = this->chstr; } +void RichString_appendChr(RichString* this, char c, int count) { + int from = this->chlen; + int newLen = from + count; + RichString_setLen(this, newLen); + for (int i = from; i < newLen; i++) { + RichString_setChar(this, i, c); + } +} + void RichString_setAttr(RichString* this, int attrs) { RichString_setAttrn(this, attrs, 0, this->chlen - 1); } diff --git a/RichString.h b/RichString.h index 12b09540..262befc5 100644 --- a/RichString.h +++ b/RichString.h @@ -50,6 +50,8 @@ void RichString_prune(RichString* this); void RichString_setAttr(RichString* this, int attrs); +void RichString_appendChr(RichString* this, char c, int count); + void RichString_append(RichString* this, int attrs, const char* data); void RichString_appendn(RichString* this, int attrs, const char* data, int len);