From e7372d18a1a661d8c3dba9f51e1f17b5f94171a7 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Wed, 10 Jan 2024 11:17:08 +0100 Subject: New upstream version 3.3.0 --- Meter.c | 145 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 64 deletions(-) (limited to 'Meter.c') diff --git a/Meter.c b/Meter.c index 164c4d3..86f8885 100644 --- a/Meter.c +++ b/Meter.c @@ -13,13 +13,13 @@ in the source distribution for its full text. #include #include #include -#include #include "CRT.h" #include "Macros.h" #include "Object.h" #include "ProvideCurses.h" #include "RichString.h" +#include "Row.h" #include "Settings.h" #include "XUtils.h" @@ -32,12 +32,12 @@ const MeterClass Meter_class = { } }; -Meter* Meter_new(const struct ProcessList_* pl, unsigned int param, const MeterClass* type) { +Meter* Meter_new(const Machine* host, unsigned int param, const MeterClass* type) { Meter* this = xCalloc(1, sizeof(Meter)); Object_setClass(this, type); this->h = 1; this->param = param; - this->pl = pl; + this->host = host; this->curItems = type->maxItems; this->curAttributes = NULL; this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL; @@ -50,32 +50,40 @@ Meter* Meter_new(const struct ProcessList_* pl, unsigned int param, const MeterC return this; } -int Meter_humanUnit(char* buffer, unsigned long int value, size_t size) { - const char* prefix = "KMGTPEZY"; - unsigned long int powi = 1; - unsigned int powj = 1, precision = 2; +/* Converts 'value' in kibibytes into a human readable string. + Example output strings: "0K", "1023K", "98.7M" and "1.23G" */ +int Meter_humanUnit(char* buffer, double value, size_t size) { + size_t i = 0; - for (;;) { - if (value / 1024 < powi) - break; - - if (prefix[1] == '\0') + assert(value >= 0.0); + while (value >= ONE_K) { + if (i >= ARRAYSIZE(unitPrefixes) - 1) { + if (value > 9999.0) { + return xSnprintf(buffer, size, "inf"); + } break; + } - powi *= 1024; - ++prefix; + value /= ONE_K; + ++i; } - if (*prefix == 'K') - precision = 0; + int precision = 0; - for (; precision > 0; precision--) { - powj *= 10; - if (value / powi < powj) - break; + if (i > 0) { + // Fraction digits for mebibytes and above + precision = value <= 99.9 ? (value <= 9.99 ? 2 : 1) : 0; + + // Round up if 'value' is in range (99.9, 100) or (9.99, 10) + if (precision < 2) { + double limit = precision == 1 ? 10.0 : 100.0; + if (value < limit) { + value = limit; + } + } } - return snprintf(buffer, size, "%.*f%c", precision, (double) value / powi, *prefix); + return xSnprintf(buffer, size, "%.*f%c", precision, value, unitPrefixes[i]); } void Meter_delete(Object* cast) { @@ -86,7 +94,7 @@ void Meter_delete(Object* cast) { if (Meter_doneFn(this)) { Meter_done(this); } - free(this->drawData); + free(this->drawData.values); free(this->caption); free(this->values); free(this); @@ -121,8 +129,9 @@ void Meter_setMode(Meter* this, int modeIndex) { } } else { assert(modeIndex >= 1); - free(this->drawData); - this->drawData = NULL; + free(this->drawData.values); + this->drawData.values = NULL; + this->drawData.nValues = 0; const MeterMode* mode = Meter_modes[modeIndex]; this->draw = mode->draw; @@ -224,8 +233,8 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) { int offset = 0; for (uint8_t i = 0; i < this->curItems; i++) { double value = this->values[i]; - value = CLAMP(value, 0.0, this->total); - if (value > 0) { + if (isPositive(value) && this->total > 0.0) { + value = MINIMUM(value, this->total); blockSizes[i] = ceil((value / this->total) * w); } else { blockSizes[i] = 0; @@ -236,6 +245,7 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) { for (int j = offset; j < nextOffset; j++) if (RichString_getCharVal(bar, startPos + j) == ' ') { if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { + assert(i < strlen(BarMeterMode_characters)); RichString_setChar(&bar, startPos + j, BarMeterMode_characters[i]); } else { RichString_setChar(&bar, startPos + j, '|'); @@ -287,13 +297,46 @@ static const char* const GraphMeterMode_dotsAscii[] = { }; static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { - const ProcessList* pl = this->pl; + const char* caption = Meter_getCaption(this); + attrset(CRT_colors[METER_TEXT]); + const int captionLen = 3; + mvaddnstr(y, x, caption, captionLen); + x += captionLen; + w -= captionLen; + + GraphData* data = &this->drawData; + assert(data->nValues / 2 <= INT_MAX); + if (w > (int)(data->nValues / 2) && MAX_METER_GRAPHDATA_VALUES > data->nValues) { + size_t oldNValues = data->nValues; + data->nValues = MAXIMUM(oldNValues + oldNValues / 2, (size_t)w * 2); + data->nValues = MINIMUM(data->nValues, MAX_METER_GRAPHDATA_VALUES); + data->values = xReallocArray(data->values, data->nValues, sizeof(*data->values)); + memmove(data->values + (data->nValues - oldNValues), data->values, oldNValues * sizeof(*data->values)); + memset(data->values, 0, (data->nValues - oldNValues) * sizeof(*data->values)); + } + + const size_t nValues = data->nValues; + if (nValues < 1) + return; + + const Machine* host = this->host; + if (!timercmp(&host->realtime, &(data->time), <)) { + int globalDelay = host->settings->delay; + struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay % 10) * 100000L }; + timeradd(&host->realtime, &delay, &(data->time)); - if (!this->drawData) { - this->drawData = xCalloc(1, sizeof(GraphData)); + memmove(&data->values[0], &data->values[1], (nValues - 1) * sizeof(*data->values)); + + data->values[nValues - 1] = sumPositiveValues(this->values, this->curItems); + } + + if (w <= 0) + return; + + if ((size_t)w > nValues / 2) { + x += w - nValues / 2; + w = nValues / 2; } - GraphData* data = this->drawData; - const int nValues = METER_GRAPHDATA_SIZE; const char* const* GraphMeterMode_dots; int GraphMeterMode_pixPerRow; @@ -308,38 +351,12 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { GraphMeterMode_pixPerRow = PIXPERROW_ASCII; } - const char* caption = Meter_getCaption(this); - attrset(CRT_colors[METER_TEXT]); - int captionLen = 3; - mvaddnstr(y, x, caption, captionLen); - x += captionLen; - w -= captionLen; - - if (!timercmp(&pl->realtime, &(data->time), <)) { - int globalDelay = this->pl->settings->delay; - struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay % 10) * 100000L }; - timeradd(&pl->realtime, &delay, &(data->time)); - - for (int i = 0; i < nValues - 1; i++) - data->values[i] = data->values[i + 1]; - - double value = 0.0; - for (uint8_t i = 0; i < this->curItems; i++) - value += this->values[i]; - data->values[nValues - 1] = value; - } - - int i = nValues - (w * 2), k = 0; - if (i < 0) { - k = -i / 2; - i = 0; - } - for (; i < nValues - 1; i += 2, k++) { + size_t i = nValues - (size_t)w * 2; + for (int col = 0; i < nValues - 1; i += 2, col++) { int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT; - if (this->total < 1) - this->total = 1; - int v1 = CLAMP((int) lround(data->values[i] / this->total * pix), 1, pix); - int v2 = CLAMP((int) lround(data->values[i + 1] / this->total * pix), 1, pix); + double total = MAXIMUM(this->total, 1); + int v1 = CLAMP((int) lround(data->values[i] / total * pix), 1, pix); + int v2 = CLAMP((int) lround(data->values[i + 1] / total * pix), 1, pix); int colorIdx = GRAPH_1; for (int line = 0; line < GRAPH_HEIGHT; line++) { @@ -347,7 +364,7 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { int line2 = CLAMP(v2 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow); attrset(CRT_colors[colorIdx]); - mvaddstr(y + line, x + k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]); + mvaddstr(y + line, x + col, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]); colorIdx = GRAPH_2; } } @@ -367,7 +384,7 @@ static const char* const LEDMeterMode_digitsAscii[] = { static const char* const LEDMeterMode_digitsUtf8[] = { "┌──┐", " ┐ ", "╶──┐", "╶──┐", "╷ ╷", "┌──╴", "┌──╴", "╶──┐", "┌──┐", "┌──┐", "│ │", " │ ", "┌──┘", " ──┤", "└──┤", "└──┐", "├──┐", " │", "├──┤", "└──┤", - "└──┘", " ╵ ", "└──╴", "╶──┘", " ╵", "╶──┘", "└──┘", " ╵", "└──┘", " ──┘" + "└──┘", " ╵ ", "└──╴", "╶──┘", " ╵", "╶──┘", "└──┘", " ╵", "└──┘", "╶──┘" }; #endif -- cgit v1.2.3