From cd88d4538be2f4e0a67a99fd6b2c258ef2018ed9 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Sat, 30 Sep 2017 02:22:22 -0500 Subject: [PATCH] top: extend utf-8 multi-byte support to users & groups Since all the necessary utf-8 plumbing is now in place this commit will extend multi-byte support to user and group names. Now top will be on a par with the ps guy. [ plus, it's also my way of showing appreciation for ] [ all those investments silently made by translators ] Reference(s): https://gitlab.com/procps-ng/procps/issues/68 Signed-off-by: Jim Warner --- top/top.c | 35 ++++++++++++++++++++++++++++++----- top/top.h | 1 + 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/top/top.c b/top/top.c index 412b4476..d0b8bdc0 100644 --- a/top/top.c +++ b/top/top.c @@ -1629,6 +1629,25 @@ static inline const char *make_str (const char *str, int width, int justr, int c } // end: make_str + /* + * Make and then justify a potentially multi-byte character string, + * and include a visual clue should tuncation be necessary. */ +static inline const char *make_str_utf8 (const char *str, int width, int justr, int col) { + static char buf[SCREENMAX]; + int delta = utf8_delta(str); + + if (width >= (int)strlen(str) - delta) + snprintf(buf, sizeof(buf), "%s", str); + else { + snprintf(buf, sizeof(buf), "%.*s", utf8_embody(str, width - 1), str); + delta = utf8_delta(buf); + buf[width + delta - 1] = COLPLUSCH; + AUTOX_COL(col); + } + return justify_pad(buf, width + delta, justr); +} // end: make_str_utf8 + + /* * Do some scaling then justify stuff. * We'll interpret 'num' as a kibibytes quantity and try to @@ -5495,8 +5514,13 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { #define makeVAR(v) { const char *pv = v; \ if (!q->varcolbeg) cp = make_str(pv, q->varcolsz, Js, AUTOX_NO); \ else cp = make_str(q->varcolbeg < (int)strlen(pv) ? pv + q->varcolbeg : "", q->varcolsz, Js, AUTOX_NO); } + #define varUTF8(v) { const char *pv = v; \ + if (!q->varcolbeg) cp = make_str_utf8(pv, q->varcolsz, Js, AUTOX_NO); \ + else cp = make_str_utf8((q->varcolbeg < ((int)strlen(pv) - utf8_delta(pv))) \ + ? pv + utf8_embody(pv, q->varcolbeg) : "", q->varcolsz, Js, AUTOX_NO); } #else #define makeVAR(v) cp = make_str(v, q->varcolsz, Js, AUTOX_NO) + #define varUTF8(v) cp = make_str_utf8(v, q->varcolsz, Js, AUTOX_NO) #endif #define pages2K(n) (unsigned long)( (n) << Pg2K_shft ) static char rbuf[ROWMINSIZ]; @@ -5581,7 +5605,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { cp = make_num(p->egid, W, Jn, EU_GID, 0); break; case EU_GRP: - cp = make_str(p->egroup, W, Js, EU_GRP); + cp = make_str_utf8(p->egroup, W, Js, EU_GRP); break; case EU_LXC: cp = make_str(p->lxcname, W, Js, EU_LXC); @@ -5645,7 +5669,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { makeVAR(p->supgid); break; case EU_SGN: - makeVAR(p->supgrp); + varUTF8(p->supgrp); break; case EU_SHR: cp = scale_mem(S, pages2K(p->share), W, Jn); @@ -5685,13 +5709,13 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { cp = make_num(p->euid, W, Jn, EU_UED, 0); break; case EU_UEN: - cp = make_str(p->euser, W, Js, EU_UEN); + cp = make_str_utf8(p->euser, W, Js, EU_UEN); break; case EU_URD: cp = make_num(p->ruid, W, Jn, EU_URD, 0); break; case EU_URN: - cp = make_str(p->ruser, W, Js, EU_URN); + cp = make_str_utf8(p->ruser, W, Js, EU_URN); break; case EU_USD: cp = make_num(p->suid, W, Jn, EU_USD, 0); @@ -5700,7 +5724,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { cp = scale_mem(S, (p->vm_swap + p->vm_rss), W, Jn); break; case EU_USN: - cp = make_str(p->suser, W, Js, EU_USN); + cp = make_str_utf8(p->suser, W, Js, EU_USN); break; case EU_VRT: cp = scale_mem(S, pages2K(p->size), W, Jn); @@ -5749,6 +5773,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) { } return rbuf; #undef makeVAR + #undef varUTF8 #undef pages2K } // end: task_show diff --git a/top/top.h b/top/top.h index be5abf5c..81c1a986 100644 --- a/top/top.h +++ b/top/top.h @@ -713,6 +713,7 @@ typedef struct WIN_t { //atic inline const char *make_chr (const char ch, int width, int justr); //atic inline const char *make_num (long num, int width, int justr, int col, int noz); //atic inline const char *make_str (const char *str, int width, int justr, int col); +//atic inline const char *make_str_utf8 (const char *str, int width, int justr, int col); //atic const char *scale_mem (int target, unsigned long num, int width, int justr); //atic const char *scale_num (unsigned long num, int width, int justr); //atic const char *scale_pcnt (float num, int width, int justr);