From e75c083ac979beda09716774a6c80ae943c84149 Mon Sep 17 00:00:00 2001 From: Martin Rys Date: Sat, 28 Sep 2024 13:37:08 +0200 Subject: [PATCH] Try to keep text highlighting with highlighted processes This tries to keep special markup like large numbers and other special markup inside a process row even when such a line has been highlighted by being selected, followed, or otherwise marked in the list view. Alternate take on PR #434. --- Panel.c | 2 +- RichString.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ RichString.h | 4 +++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Panel.c b/Panel.c index 4784a6585..05e009403 100644 --- a/Panel.c +++ b/Panel.c @@ -289,7 +289,7 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect } if (item.highlightAttr) { attrset(item.highlightAttr); - RichString_setAttr(&item, item.highlightAttr); + RichString_setAttr_preserveWithStandout(&item, item.highlightAttr); this->selectedLen = itemLen; } mvhline(y + line, x, ' ', this->w); diff --git a/RichString.c b/RichString.c index 390beb073..4fbea1cdd 100644 --- a/RichString.c +++ b/RichString.c @@ -62,6 +62,10 @@ void RichString_rewind(RichString* this, int count) { RichString_setLen(this, this->chlen - count); } +void RichString_setAttr_preserveWithStandout(RichString* this, int attrs) { + RichString_setAttrn_preserveWithStandout(this, attrs, 0, this->chlen - 1); +} + #ifdef HAVE_LIBNCURSESW static size_t mbstowcs_nonfatal(wchar_t* restrict dest, const char* restrict src, size_t n) { @@ -160,6 +164,41 @@ inline void RichString_setAttrn(RichString* this, int attrs, int start, int char } } +void RichString_setAttrn_preserveWithStandout(RichString* this, int attrs, int start, int finish) { + finish = CLAMP(finish, 0, this->chlen - 1); + + // Extract the foreground and background color indexes from the passed attrs + short passed_color_pair_number = (short)PAIR_NUMBER(attrs); + short passed_fg_color = -1, passed_bg_color = -1; + if (passed_color_pair_number != 0) { + pair_content(passed_color_pair_number, &passed_fg_color, &passed_bg_color); + } + + cchar_t* ch = this->chptr + start; + for (int i = start; i <= finish; i++) { + // Extract foreground and background color indexes from the current char + short currentCharPairNum = (short)PAIR_NUMBER(ch->attr); + short before_fg_color = -1, before_bg_color = -1; + if (currentCharPairNum != 0) { + pair_content(currentCharPairNum, &before_fg_color, &before_bg_color); + } + + // TODO: When text color matches higlight, the resulting STANDOUT is the same as on default text, + // so we at least set italics + chtype attrToPass = A_STANDOUT; + if (before_fg_color == passed_bg_color) { + attrToPass |= A_ITALIC; + } + // If current char is not a space and its ColorPair Index is not the default 0, + // apply our own attrToPass with STANDOUT + optionally ITALICS, + // instead of the passed attrs, which has the BG highlight color + ch->attr = (ch->chars[0] != L' ' && currentCharPairNum != 0) + ? (ch->attr | attrToPass) + : (unsigned int)attrs; + ch++; + } +} + void RichString_appendChr(RichString* this, int attrs, char c, int count) { int from = this->chlen; int newLen = from + count; @@ -210,6 +249,41 @@ void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) } } +void RichString_setAttrn_preserveWithStandout(RichString* this, int attrs, int start, int finish) { + finish = CLAMP(finish, 0, this->chlen - 1); + + // Extract the foreground and background color indexes from the passed attrs + short passed_color_pair_number = (short)PAIR_NUMBER(attrs); + short passed_fg_color = -1, passed_bg_color = -1; + if (passed_color_pair_number != 0) { + pair_content(passed_color_pair_number, &passed_fg_color, &passed_bg_color); + } + + chtype* ch = this->chptr + start; + for (int i = start; i <= finish; i++) { + // Extract foreground and background color indexes from the current char + short currentCharPairNum = (short)PAIR_NUMBER(*ch); + short before_fg_color = -1, before_bg_color = -1; + if (currentCharPairNum != 0) { + pair_content(currentCharPairNum, &before_fg_color, &before_bg_color); + } + + // TODO: When text color matches higlight, the resulting STANDOUT is the same as on default text, + // so we at least set italics + chtype attrToPass = A_STANDOUT; + if (before_fg_color == passed_bg_color) { + attrToPass |= A_ITALIC; + } + // If current char is not a space and its ColorPair Index is not the default 0, + // apply our own attrToPass with STANDOUT + optionally ITALICS, + // instead of the passed attrs, which has the BG highlight color + *ch = ((*ch & A_CHARTEXT) != L' ' && currentCharPairNum != 0) + ? *ch | attrToPass + : (*ch & A_CHARTEXT) | (unsigned int)attrs; + ch++; + } +} + void RichString_appendChr(RichString* this, int attrs, char c, int count) { int from = this->chlen; int newLen = from + count; diff --git a/RichString.h b/RichString.h index 7783378bc..12e68fded 100644 --- a/RichString.h +++ b/RichString.h @@ -52,10 +52,14 @@ void RichString_rewind(RichString* this, int count); void RichString_setAttrn(RichString* this, int attrs, int start, int charcount); +void RichString_setAttrn_preserveWithStandout(RichString* this, int attrs, int start, int finish); + int RichString_findChar(const RichString* this, char c, int start); void RichString_setAttr(RichString* this, int attrs); +void RichString_setAttr_preserveWithStandout(RichString* this, int attrs); + void RichString_appendChr(RichString* this, int attrs, char c, int count); /* All appending and writing functions return the number of written characters (not columns). */