Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial code improvements with respect to Clang 19 warnings #1516

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
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
31 changes: 19 additions & 12 deletions Meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@ static inline void Meter_displayBuffer(const Meter* this, RichString* out) {
/* ---------- TextMeterMode ---------- */

static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
if (w <= 0)
return;

const char* caption = Meter_getCaption(this);
attrset(CRT_colors[METER_TEXT]);
mvaddnstr(y, x, caption, w);
attrset(CRT_colors[RESET_COLOR]);

int captionLen = strlen(caption);
x += captionLen;
w -= captionLen;
if (w <= 0)
size_t captionLen = strlen(caption);
if ((size_t)w <= captionLen)
return;
x += (int)captionLen;
w -= (int)captionLen;

RichString_begin(out);
Meter_displayBuffer(this, &out);
Expand Down Expand Up @@ -301,6 +304,10 @@ static void LEDMeterMode_drawDigit(int x, int y, int n) {
}

static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
assert(x >= 0);
if (w <= 0)
return;

#ifdef HAVE_LIBNCURSESW
if (CRT_utf8)
LEDMeterMode_digits = LEDMeterMode_digitsUtf8;
Expand All @@ -318,25 +325,25 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
y + 2;
attrset(CRT_colors[LED_COLOR]);
const char* caption = Meter_getCaption(this);
mvaddstr(yText, x, caption);
int xx = x + strlen(caption);
mvaddnstr(yText, x, caption, w);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one is a little beyond my knowledge. According to man pages, the n in mvaddnstr refers to number of "characters" to print. However, what I really want to limit is the number of terminal columns, not the number of Unicode characters (this distinction is needed if East Asian Wide characters are in the strings).

Perhaps a good way is to test how this function call would output, would it be "12" or just "":

/* "1234 fullwidth" */
addnstr("\uFF11\uFF12\uFF13\uFF14 fullwidth", 2);

Copy link
Member

Choose a reason for hiding this comment

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

What about wcswidth(3)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What I wish is a function that does an inverse of wcswidth(3). wcswidth() returns the terminal column width given a string and a number of (Unicode) characters limit. What I wished is retrieving the number of characters (or number of bytes) given a string and a column width limit. RichString_appendnWideColumns() might give the closest I need, but I want a function that operates on a const char* rather than a RichString object. Maybe I would write one from scratch?

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately that is easier said than actual done, but based on the fact that wcswidth returns >=0 you can probably build something like this by calling wcwidth(3) for each character in turn until you overshoot the limit, in which case you know the last character was too much (this accounts for zero-width-combiners and other special cases). The down-side is, that you will need to transform the const char* into wchar_t* first, thus having this functionality live with the other RichString functions might be reasonable.

NB: There's actually an issue that might benefit from this functionality in #462 IIRC.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@BenBE Yes, I'm aware of PR #462. And perhaps PR #1231 can benefit, too, as I wish this function would work as a word wrapper that is also CJK-aware.

size_t xx = (size_t)x + strlen(caption);
int len = RichString_sizeVal(out);
for (int i = 0; i < len; i++) {
for (size_t i = 0; i < (size_t)len; i++) {
int c = RichString_getCharVal(out, i);
if (c >= '0' && c <= '9') {
if (xx - x + 4 > w)
if (xx + 4 > (unsigned int)x + (unsigned int)w)
break;

LEDMeterMode_drawDigit(xx, y, c - '0');
LEDMeterMode_drawDigit((int)xx, y, c - '0');
xx += 4;
} else {
if (xx - x + 1 > w)
if (xx + 1 > (unsigned int)x + (unsigned int)w)
break;
#ifdef HAVE_LIBNCURSESW
const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */
mvadd_wch(yText, xx, &wc);
mvadd_wch(yText, (int)xx, &wc);
#else
mvaddch(yText, xx, c);
mvaddch(yText, (int)xx, c);
#endif
xx += 1;
}
Expand Down
12 changes: 6 additions & 6 deletions Row.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,23 +428,23 @@ void Row_printNanoseconds(RichString* str, unsigned long long totalNanoseconds,
}

unsigned long long totalSeconds = totalMicroseconds / 1000000;
unsigned long microseconds = totalMicroseconds % 1000000;
uint32_t microseconds = totalMicroseconds % 1000000;
if (totalSeconds < 60) {
int width = 5;
unsigned long fraction = microseconds / 10;
uint32_t fraction = microseconds / 10;
if (totalSeconds >= 10) {
width--;
fraction /= 10;
}
len = xSnprintf(buffer, sizeof(buffer), "%u.%0*lus ", (unsigned int)totalSeconds, width, fraction);
len = xSnprintf(buffer, sizeof(buffer), "%u.%0*lus ", (unsigned int)totalSeconds, width, (unsigned long)fraction);
RichString_appendnAscii(str, baseColor, buffer, len);
return;
}

if (totalSeconds < 600) {
unsigned int minutes = totalSeconds / 60;
unsigned int seconds = totalSeconds % 60;
unsigned int milliseconds = microseconds / 1000;
unsigned int minutes = (unsigned int)totalSeconds / 60;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't the cast here happen after the division?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not necessary because of the (totalSeconds < 600) conditional. Although I argue this is more of a style issue...
(Compiler should catch that (unsigned int)(totalSeconds / 60) can be optimized to ((unsigned int)totalSeconds) / 60, no?)

Copy link
Member

Choose a reason for hiding this comment

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

Not necessarily, as (unsigned int)((1UL<<32) / 60) != (unsigned int)(1UL<<32) / 60.

Won't happen in this case based on the previous check, but the correctness should take priority here.

unsigned int seconds = (unsigned int)totalSeconds % 60;
unsigned int milliseconds = (unsigned int)(microseconds / 1000);
len = xSnprintf(buffer, sizeof(buffer), "%u:%02u.%03u ", minutes, seconds, milliseconds);
RichString_appendnAscii(str, baseColor, buffer, len);
return;
Expand Down