Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions DisplayOptionsPanel.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges)));
Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24 * 60 * 60));
Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2));

#ifdef HAVE_LIBNCURSESW
if(CRT_utf8)
Panel_add(super, (Object*) NumberItem_newByRef("Bar Type (0 - default)", (int*)&(settings->barType), 0, 0, BAR_METER_NUM_STYLES-1));
#endif

#ifdef HAVE_LIBHWLOC
Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity)));
#endif
Expand Down
40 changes: 38 additions & 2 deletions Meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ static void TextMeterMode_draw(Meter* this, int x, int y, int w) {

static const char BarMeterMode_characters[] = "|#*@$%&.";

#ifdef HAVE_LIBNCURSESW
const wchar_t* bars[BAR_METER_NUM_STYLES] = {
L"|",
L"#",
L"⣿⡀⡄⡆⡇⣇⣧⣷",
L"█░░▒▒▓▓█",
L"█▏▎▍▌▋▊▉",
L"█▁▂▃▄▅▆▇",
L"█▌▌▌▌███"
};
#endif

static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
assert(x >= 0);
assert(w <= INT_MAX - x);
Expand Down Expand Up @@ -149,6 +161,14 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
assert(startPos + w <= RichString_sizeVal(bar));

int blockSizes[10];
#ifdef HAVE_LIBNCURSESW
Settings* settings = this->host->settings;
assert(settings->barType < ( sizeof(bars) / sizeof(wchar_t*) ));
assert(settings->barType >= 0);
const wchar_t* currBar = bars[settings->barType];
int barLen = (int)wcslen(currBar);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this function call redundant when you have declared the list of bars to have equal length.

Not sure if this is what you intended, but I think the bar meter characters can be defined with variable widths if you wish.

Like this:

static const wchar_t* BarMeterMode_drawStyles[] = {
   L"|",
   L"#",
   L"⡀⡄⡆⡇⣇⣧⣷⣿",
   L"░▒▓█",
   L"▏▎▍▌▋▊▉█",
   L"▁▂▃▄▅▆▇█",
   L"▌█",
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bars currently have all the same length, but the intention is to actually allow for bars to contain different number of symbols.

int extraWidth = 0;
#endif

// First draw in the bar[] buffer...
int offset = 0;
Expand All @@ -158,19 +178,35 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
value = MINIMUM(value, this->total);
blockSizes[i] = ceil((value / this->total) * w);
blockSizes[i] = MINIMUM(blockSizes[i], w - offset);

#ifdef HAVE_LIBNCURSESW
extraWidth = (int)ceil((value / this->total) * w * barLen) % barLen;
#endif
Comment on lines 179 to +184
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs some minor update. The extraWidth calculation probably should re-use the value calculated in the blockSizes[i] assignments above.

} else {
blockSizes[i] = 0;
}
int nextOffset = offset + blockSizes[i];
for (int j = offset; j < nextOffset; j++)
for (int j = offset; j < nextOffset; j++) {
if (RichString_getCharVal(bar, startPos + j) == ' ') {
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one thing I wish to add when the feature of changing bar drawing character is added. It's this:

Suggested change
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
if (CRT_colorScheme == COLORSCHEME_MONOCHROME && Meter_maxItems(this) != 1) {

Make the bar character changeable for meters with only one item.

--- a/Meter.h
+++ b/Meter.h
@@ -100,6 +100,7 @@ typedef struct MeterClass_ {
 #define Meter_attributes(this_)        As_Meter(this_)->attributes
 #define Meter_name(this_)              As_Meter(this_)->name
 #define Meter_uiName(this_)            As_Meter(this_)->uiName
+#define Meter_maxItems(this_)          As_Meter(this_)->maxItems
 #define Meter_isMultiColumn(this_)     As_Meter(this_)->isMultiColumn
 #define Meter_isPercentChart(this_)    As_Meter(this_)->isPercentChart
 

assert(i < strlen(BarMeterMode_characters));
RichString_setChar(&bar, startPos + j, BarMeterMode_characters[i]);
} else {
}
#ifdef HAVE_LIBNCURSESW
else if(CRT_utf8 && settings->barType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole block of else if (CRT_utf8 && settings->barType) { ... } can merge with the else { ... } block below so we can reduce duplicate code.

if(j==nextOffset-1){
RichString_setChar(&bar, startPos+nextOffset-1, currBar[extraWidth]);
} else {
RichString_setChar(&bar, startPos + j, currBar[0]);
}
}
#endif
else {
RichString_setChar(&bar, startPos + j, '|');
}
}
}

offset = nextOffset;
}

Expand Down
1 change: 1 addition & 0 deletions MeterMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ typedef unsigned int MeterModeId;
(1 << LED_METERMODE) | \
0) // Avoids edits when updating

#define BAR_METER_NUM_STYLES 7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define BAR_METER_NUM_STYLES 7
extern const size_t bar_meter_num_styles;

And below the definition of bars' for the meter styles in Meter.c`:

const size_t bar_meter_num_styles = sizeof(bars) / sizeof(*bars);

This avoids an additional point of manual updating.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BenBE This has the problem that when compiling Setting.c, compiler cannot inline the constant but has to refer to the external variable for the number. In other words, the compiled code would be sub-optimal.

I think the better approach is to move the definitions of the bar styles into the header. Look at the unitPrefixes definition in XUtils.h for what I mean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware of this downside, but AFAICT there are no real places where looking up this constant happens inside a tight loop …

#endif
16 changes: 16 additions & 0 deletions Settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "MeterMode.h"
#include "config.h" // IWYU pragma: keep

#include "Settings.h"
Expand Down Expand Up @@ -516,6 +517,13 @@ static bool Settings_read(Settings* this, const char* fileName, const Machine* h
didReadMeters = true;
} else if (String_eq(option[0], "hide_function_bar")) {
this->hideFunctionBar = atoi(option[1]);
#ifdef HAVE_LIBNCURSESW
} else if (String_eq(option[0], "bar_type")) {
long value = strtol(option[1], NULL, 10);
if (value < 0 || value > BAR_METER_NUM_STYLES)
value = 0;
this->barType = (unsigned int)value;
#endif
#ifdef HAVE_LIBHWLOC
} else if (String_eq(option[0], "topology_affinity")) {
this->topologyAffinity = !!atoi(option[1]);
Expand Down Expand Up @@ -714,6 +722,9 @@ int Settings_write(const Settings* this, bool onCrash) {
#endif
printSettingInteger("delay", (int) this->delay);
printSettingInteger("hide_function_bar", (int) this->hideFunctionBar);
#ifdef HAVE_LIBNCURSESW
printSettingInteger("bar_type", (int) this->barType);
#endif
#ifdef HAVE_LIBHWLOC
printSettingInteger("topology_affinity", this->topologyAffinity);
#endif
Expand Down Expand Up @@ -821,6 +832,11 @@ Settings* Settings_new(const Machine* host, Hashtable* dynamicMeters, Hashtable*
this->showMergedCommand = false;
this->hideFunctionBar = 0;
this->headerMargin = true;

#ifdef HAVE_LIBNCURSESW
this->barType = 0;
#endif

#ifdef HAVE_LIBHWLOC
this->topologyAffinity = false;
#endif
Expand Down
3 changes: 3 additions & 0 deletions Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ typedef struct Settings_ {
bool enableMouse;
#endif
int hideFunctionBar; // 0 - off, 1 - on ESC until next input, 2 - permanently
#ifdef HAVE_LIBNCURSESW
unsigned int barType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the proposed bar drawing styles has | (vertical bar, the default), and # (number sign), both can be drawn in ASCII-only mode, I think we can remove the #ifdef HAVE_LIBNCURSESW conditional and allow the setting to be available in both ASCII-only build and Unicode build of htop.

Note: only the first two drawing styles can be selected in ASCII. The rest can be guarded in the #ifdef HAVE_LIBNCURSESW so they require Unicode to enable:

#ifdef HAVE_LIBNCURSESW
static const wchar_t* barMeterDrawStyles[] = {
   L"|",
   L"#",
   L"⡀⡄⡆⡇⣇⣧⣷⣿",
   L"░▒▓█",
   L"▏▎▍▌▋▊▉█",
   L"▁▂▃▄▅▆▇█",
   L"▌█",
};
#else
static const char* barMeterDrawStyles[] = {
   "|",
   "#"
};
#endif
static const size_t numBarMeterStyles = ARRAYSIZE(barMeterDrawStyles);

#endif
#ifdef HAVE_LIBHWLOC
bool topologyAffinity;
#endif
Expand Down