Skip to content

Commit 6f948d3

Browse files
authored
Merge pull request #1707 from Explorer09/string-width
Introduce strnlen() and use it for some string width calculations
2 parents 3c32af7 + e9e8001 commit 6f948d3

File tree

8 files changed

+62
-27
lines changed

8 files changed

+62
-27
lines changed

Action.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -402,19 +402,28 @@ static Htop_Reaction actionPrevScreen(State* st) {
402402

403403
Htop_Reaction Action_setScreenTab(State* st, int x) {
404404
Settings* settings = st->host->settings;
405-
int s = SCREEN_TAB_MARGIN_LEFT;
405+
const int bracketWidth = (int)strlen("[]");
406+
407+
if (x < SCREEN_TAB_MARGIN_LEFT) {
408+
return 0;
409+
}
410+
411+
int rem = x - SCREEN_TAB_MARGIN_LEFT;
406412
for (unsigned int i = 0; i < settings->nScreens; i++) {
407-
if (x < s) {
408-
return 0;
409-
}
410413
const char* tab = settings->screens[i]->heading;
411-
int len = strlen(tab);
412-
if (x < s + len + 2) {
414+
int width = rem >= bracketWidth ? (int)strnlen(tab, rem - bracketWidth + 1) : 0;
415+
if (width >= rem - bracketWidth + 1) {
413416
settings->ssIndex = i;
414417
setActiveScreen(settings, st, i);
415418
return HTOP_UPDATE_PANELHDR | HTOP_REFRESH | HTOP_REDRAW_BAR;
416419
}
417-
s += len + 2 + SCREEN_TAB_COLUMN_GAP;
420+
421+
rem -= bracketWidth + width;
422+
if (rem < SCREEN_TAB_COLUMN_GAP) {
423+
return 0;
424+
}
425+
426+
rem -= SCREEN_TAB_COLUMN_GAP;
418427
}
419428
return 0;
420429
}

AffinityPanel.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ in the source distribution for its full text.
1010
#include "AffinityPanel.h"
1111

1212
#include <assert.h>
13+
#include <limits.h> // IWYU pragma: keep
1314
#include <stdbool.h>
1415
#include <stdlib.h>
1516
#include <string.h>
@@ -321,7 +322,9 @@ static MaskItem* AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, u
321322
}
322323

323324
/* "[x] " + "|- " * depth + ("- ")?(if root node) + name */
324-
unsigned width = 4 + 3 * depth + (2 * !depth) + strlen(buf);
325+
unsigned int indent_width = 4 + 3 * depth + (2 * !depth);
326+
assert(sizeof(buf) <= INT_MAX - indent_width);
327+
unsigned int width = indent_width + (unsigned int)strlen(buf);
325328
if (width > this->width) {
326329
this->width = width;
327330
}

Meter.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
5454
assert(w <= INT_MAX - x);
5555

5656
const char* caption = Meter_getCaption(this);
57-
if (w >= 1) {
57+
if (w > 0) {
5858
attrset(CRT_colors[METER_TEXT]);
5959
mvaddnstr(y, x, caption, w);
6060
}
6161
attrset(CRT_colors[RESET_COLOR]);
6262

63-
int captionLen = strlen(caption);
64-
w -= captionLen;
65-
if (w < 1) {
63+
int captionWidth = w > 0 ? (int)strnlen(caption, w) : 0;
64+
if (w <= captionWidth) {
6665
return;
6766
}
68-
x += captionLen;
67+
w -= captionWidth;
68+
x += captionWidth;
6969

7070
RichString_begin(out);
7171
Meter_displayBuffer(this, &out);
@@ -336,15 +336,15 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
336336
attrset(CRT_colors[LED_COLOR]);
337337

338338
const char* caption = Meter_getCaption(this);
339-
if (w >= 1) {
339+
if (w > 0) {
340340
mvaddnstr(yText, x, caption, w);
341341
}
342342

343-
int captionLen = strlen(caption);
344-
if (w <= captionLen) {
343+
int captionWidth = w > 0 ? (int)strnlen(caption, w) : 0;
344+
if (w <= captionWidth) {
345345
goto end;
346346
}
347-
int xx = x + captionLen;
347+
int xx = x + captionWidth;
348348

349349
#ifdef HAVE_LIBNCURSESW
350350
if (CRT_utf8)

Row.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,15 @@ const char* RowField_alignedTitle(const Settings* settings, RowField field) {
177177
}
178178

179179
RowField RowField_keyAt(const Settings* settings, int at) {
180-
const RowField* fields = (const RowField*) settings->ss->fields;
180+
const RowField* fields = settings->ss->fields;
181181
RowField field;
182-
int x = 0;
182+
int rem = at;
183183
for (int i = 0; (field = fields[i]); i++) {
184-
int len = strlen(RowField_alignedTitle(settings, field));
185-
if (at >= x && at <= x + len) {
184+
int len = rem > 0 ? (int)strnlen(RowField_alignedTitle(settings, field), rem) : 0;
185+
if (rem <= len) {
186186
return field;
187187
}
188-
x += len;
188+
rem -= len;
189189
}
190190
return COMM;
191191
}

ScreenManager.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,18 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
161161
}
162162

163163
static inline bool drawTab(const int* y, int* x, int l, const char* name, bool cur) {
164+
assert(*x >= 0);
165+
assert(*x < l);
166+
164167
attrset(CRT_colors[cur ? SCREENS_CUR_BORDER : SCREENS_OTH_BORDER]);
165168
mvaddch(*y, *x, '[');
166169
(*x)++;
167170
if (*x >= l)
168171
return false;
169-
int nameLen = strlen(name);
170-
int n = MINIMUM(l - *x, nameLen);
172+
int nameWidth = (int)strnlen(name, l - *x);
171173
attrset(CRT_colors[cur ? SCREENS_CUR_TEXT : SCREENS_OTH_TEXT]);
172-
mvaddnstr(*y, *x, name, n);
173-
*x += n;
174+
mvaddnstr(*y, *x, name, nameWidth);
175+
*x += nameWidth;
174176
if (*x >= l)
175177
return false;
176178
attrset(CRT_colors[cur ? SCREENS_CUR_BORDER : SCREENS_OTH_BORDER]);
@@ -190,9 +192,12 @@ static void ScreenManager_drawScreenTabs(ScreenManager* this) {
190192
int y = panel->y - 1;
191193
int x = SCREEN_TAB_MARGIN_LEFT;
192194

195+
if (x >= l)
196+
goto end;
197+
193198
if (this->name) {
194199
drawTab(&y, &x, l, this->name, true);
195-
return;
200+
goto end;
196201
}
197202

198203
for (int s = 0; screens[s]; s++) {
@@ -201,6 +206,8 @@ static void ScreenManager_drawScreenTabs(ScreenManager* this) {
201206
break;
202207
}
203208
}
209+
210+
end:
204211
attrset(CRT_colors[RESET_COLOR]);
205212
}
206213

XUtils.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,17 @@ size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t
224224
return i;
225225
}
226226

227+
#ifndef HAVE_STRNLEN
228+
size_t strnlen(const char* str, size_t maxLen) {
229+
for (size_t len = 0; len < maxLen; len++) {
230+
if (!str[len]) {
231+
return len;
232+
}
233+
}
234+
return maxLen;
235+
}
236+
#endif
237+
227238
int xAsprintf(char** strp, const char* fmt, ...) {
228239
va_list vl;
229240
va_start(vl, fmt);

XUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ static inline char* String_strchrnul(const char* s, int c) {
102102
ATTR_NONNULL ATTR_ACCESS3_W(1, 3) ATTR_ACCESS3_R(2, 3)
103103
size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t size);
104104

105+
#ifndef HAVE_STRNLEN
106+
size_t strnlen(const char* str, size_t maxLen);
107+
#endif
108+
105109
ATTR_FORMAT(printf, 2, 3) ATTR_NONNULL_N(1, 2)
106110
int xAsprintf(char** strp, const char* fmt, ...);
107111

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ AC_CHECK_FUNCS([ \
372372
readlinkat \
373373
sched_getscheduler \
374374
sched_setscheduler \
375+
strnlen \
375376
])
376377

377378
# strchrnul is available in macOS since 15.4, but the user may specify an older

0 commit comments

Comments
 (0)