Skip to content

Commit 7111b6d

Browse files
committed
Wide character support in LED meter mode text
1 parent e1f171a commit 7111b6d

1 file changed

Lines changed: 62 additions & 14 deletions

File tree

Meter.c

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -414,25 +414,73 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
414414
RichString_begin(out);
415415
Meter_displayBuffer(this, &out);
416416

417-
int len = RichString_sizeVal(out);
418-
for (int i = 0; i < len; i++) {
419-
int c = RichString_getCharVal(out, i);
420-
if (c >= '0' && c <= '9') {
421-
if (xx > x + w - 4)
422-
break;
417+
#ifdef HAVE_LIBNCURSESW
418+
// If the character takes zero columns, include the character in the
419+
// substring if the working encoding is UTF-8, and ignore it otherwise.
420+
// In Unicode, combining characters are always placed after the base
421+
// character, but some legacy 8-bit encodings instead place combining
422+
// characters before the base character.
423+
const bool isUnicode = CRT_utf8;
424+
#else
425+
const bool isUnicode = false;
426+
#endif
423427

424-
LEDMeterMode_drawDigit(xx, y, c - '0');
425-
xx += 4;
426-
} else {
427-
if (xx > x + w - 1)
428+
size_t len = RichString_sizeVal(out);
429+
size_t charPos = 0;
430+
while (charPos < len) {
431+
#ifdef HAVE_LIBNCURSESW
432+
wchar_t c = 0;
433+
#else
434+
int c = 0;
435+
#endif
436+
437+
int subWidth = 0;
438+
size_t breakPos = charPos;
439+
size_t startPos = charPos;
440+
while (charPos < len && (xx + subWidth < x + w || isUnicode)) {
441+
assert(xx + subWidth <= x + w);
442+
443+
c = RichString_getCharVal(out, charPos);
444+
assert(c != 0);
445+
if (c >= '0' && c <= '9')
428446
break;
447+
429448
#ifdef HAVE_LIBNCURSESW
430-
const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */
431-
mvadd_wch(yText, xx, &wc);
449+
int cw = wcwidth(c);
450+
assert(cw >= 0);
432451
#else
433-
mvaddch(yText, xx, c);
452+
assert(isprint(c));
453+
const int cw = 1;
434454
#endif
435-
xx += 1;
455+
456+
if ((unsigned int)cw > (unsigned int)(x + w - (xx + subWidth))) {
457+
charPos = len;
458+
break;
459+
}
460+
461+
charPos++;
462+
463+
if (cw <= 0 && !isUnicode)
464+
continue;
465+
466+
subWidth += cw;
467+
breakPos = charPos;
468+
}
469+
470+
if (breakPos > startPos) {
471+
RichString_setAttrn(&out, CRT_colors[LED_COLOR], startPos, breakPos - startPos);
472+
RichString_printoffnVal(out, yText, xx, startPos, breakPos - startPos);
473+
xx += subWidth;
474+
}
475+
476+
if (c >= '0' && c <= '9') {
477+
const int cw = 4;
478+
if (cw > x + w - xx)
479+
break;
480+
481+
LEDMeterMode_drawDigit(xx, y, c - '0');
482+
xx += cw;
483+
charPos++;
436484
}
437485
}
438486
RichString_delete(&out);

0 commit comments

Comments
 (0)