From ca6b9238a39980aac650eb4bd82ace74c31a285f Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 3 Nov 2011 22:12:12 +0000 Subject: Support for UTF-8 tree drawing (thanks to Bin Guo) --- ChangeLog | 2 ++ Process.c | 25 +++++++++++++++---------- ProcessList.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- ProcessList.h | 22 ++++++++++++++++++++++ htop.c | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 957e0090..80ef0f94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ What's new in version 0.9.1 * Switch from PLPA, which is now deprecated, to HWLOC. +* Support for UTF-8 tree drawing + (thanks to Bin Guo) * Option for counting CPUs from zero (thanks to Sean Noonan) * Meters update in every screen (no longer halting while on Setup, etc.) diff --git a/Process.c b/Process.c index 0632278a..31c87406 100644 --- a/Process.c +++ b/Process.c @@ -387,21 +387,26 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel } else { char* buf = buffer; int maxIndent = 0; + const char **treeStr = this->pl->treeStr; + bool lastItem = (this->indent < 0); + int indent = (this->indent < 0 ? -this->indent : this->indent); + if (treeStr == NULL) + treeStr = ProcessList_treeStrAscii; + for (int i = 0; i < 32; i++) - if (this->indent & (1 << i)) + if (indent & (1 << i)) maxIndent = i+1; for (int i = 0; i < maxIndent - 1; i++) { - if (this->indent & (1 << i)) - snprintf(buf, n, " | "); + int written; + if (indent & (1 << i)) + written = snprintf(buf, n, "%s ", treeStr[TREE_STR_VERT]); else - snprintf(buf, n, " "); - buf += 4; - n -= 4; + written = snprintf(buf, n, " "); + buf += written; + n -= written; } - if (this->pl->direction == 1) - snprintf(buf, n, " `%s ", this->showChildren ? "-" : "+" ); - else - snprintf(buf, n, " ,%s ", this->showChildren ? "-" : "+" ); + const char* draw = treeStr[lastItem ? (this->pl->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE]; + snprintf(buf, n, "%s%s ", draw, this->showChildren ? treeStr[TREE_STR_SHUT] : treeStr[TREE_STR_OPEN] ); RichString_append(str, CRT_colors[PROCESS_TREE], buffer); Process_writeCommand(this, attr, baseattr, str); return; diff --git a/ProcessList.c b/ProcessList.c index c986cecd..b681fede 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -57,9 +57,23 @@ in the source distribution for its full text. #ifndef ProcessList_cpuId #define ProcessList_cpuId(pl, cpu) ((pl)->countCPUsFromZero ? (cpu) : (cpu)+1) #endif -}*/ -/*{ +typedef enum TreeStr_ { + TREE_STR_HORZ, + TREE_STR_VERT, + TREE_STR_RTEE, + TREE_STR_BEND, + TREE_STR_TEND, + TREE_STR_OPEN, + TREE_STR_SHUT, + TREE_STR_COUNT +} TreeStr; + +typedef enum TreeType_ { + TREE_TYPE_AUTO, + TREE_TYPE_ASCII, + TREE_TYPE_UTF8, +} TreeType; typedef struct CPUData_ { unsigned long long int totalTime; @@ -132,12 +146,34 @@ typedef struct ProcessList_ { bool highlightThreads; bool detailedCPUTime; bool countCPUsFromZero; + const char **treeStr; } ProcessList; + }*/ static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; +const char *ProcessList_treeStrAscii[TREE_STR_COUNT] = { + "-", // TREE_STR_HORZ + "|", // TREE_STR_VERT + "`", // TREE_STR_RTEE + "`", // TREE_STR_BEND + ",", // TREE_STR_TEND + "+", // TREE_STR_OPEN + "-", // TREE_STR_SHUT +}; + +const char *ProcessList_treeStrUtf8[TREE_STR_COUNT] = { + "\xe2\x94\x80", // TREE_STR_HORZ ─ + "\xe2\x94\x82", // TREE_STR_VERT │ + "\xe2\x94\x9c", // TREE_STR_RTEE ├ + "\xe2\x94\x94", // TREE_STR_BEND └ + "\xe2\x94\x8c", // TREE_STR_TEND ┌ + "+", // TREE_STR_OPEN + + "\xe2\x94\x80", // TREE_STR_SHUT ─ +}; + ProcessList* ProcessList_new(UsersTable* usersTable) { ProcessList* this; this = calloc(sizeof(ProcessList), 1); @@ -194,6 +230,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable) { this->highlightMegabytes = false; this->detailedCPUTime = false; this->countCPUsFromZero = false; + this->treeStr = NULL; return this; } @@ -282,7 +319,10 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i assert(this->processes2->items == s+1); (void)s; int nextIndent = indent | (1 << level); ProcessList_buildTree(this, process->pid, level+1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false); - process->indent = nextIndent; + if (i == size - 1) + process->indent = -nextIndent; + else + process->indent = nextIndent; } Vector_delete(children); } diff --git a/ProcessList.h b/ProcessList.h index e68ca49e..5432c187 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -60,6 +60,22 @@ in the source distribution for its full text. #define ProcessList_cpuId(pl, cpu) ((pl)->countCPUsFromZero ? (cpu) : (cpu)+1) #endif +typedef enum TreeStr_ { + TREE_STR_HORZ, + TREE_STR_VERT, + TREE_STR_RTEE, + TREE_STR_BEND, + TREE_STR_TEND, + TREE_STR_OPEN, + TREE_STR_SHUT, + TREE_STR_COUNT +} TreeStr; + +typedef enum TreeType_ { + TREE_TYPE_AUTO, + TREE_TYPE_ASCII, + TREE_TYPE_UTF8, +} TreeType; typedef struct CPUData_ { unsigned long long int totalTime; @@ -132,9 +148,15 @@ typedef struct ProcessList_ { bool highlightThreads; bool detailedCPUTime; bool countCPUsFromZero; + const char **treeStr; } ProcessList; + +extern const char *ProcessList_treeStrAscii[TREE_STR_COUNT]; + +extern const char *ProcessList_treeStrUtf8[TREE_STR_COUNT]; + ProcessList* ProcessList_new(UsersTable* usersTable); void ProcessList_delete(ProcessList* this); diff --git a/htop.c b/htop.c index 10924a1d..b71198a6 100644 --- a/htop.c +++ b/htop.c @@ -263,6 +263,7 @@ int main(int argc, char** argv) { bool userOnly = false; uid_t userId = 0; int usecolors = 1; + TreeType treeType = TREE_TYPE_AUTO; int opt, opti=0; static struct option long_opts[] = @@ -281,8 +282,10 @@ int main(int argc, char** argv) { char *lc_ctype = getenv("LC_CTYPE"); if(lc_ctype != NULL) setlocale(LC_CTYPE, lc_ctype); + else if ((lc_ctype = getenv("LC_ALL"))) + setlocale(LC_CTYPE, lc_ctype); else - setlocale(LC_CTYPE, getenv("LC_ALL")); + setlocale(LC_CTYPE, ""); /* Parse arguments */ while ((opt = getopt_long(argc, argv, "hvCs:d:u:", long_opts, &opti))) { @@ -361,6 +364,34 @@ int main(int argc, char** argv) { settings->delay = delay; if (!usecolors) settings->colorScheme = COLORSCHEME_MONOCHROME; + + if (treeType == TREE_TYPE_AUTO) { +#ifdef HAVE_LIBNCURSESW + char *locale = setlocale(LC_ALL, NULL); + if (locale == NULL || locale[0] == '\0') + locale = setlocale(LC_CTYPE, NULL); + if (locale != NULL && + (strstr(locale, "UTF-8") || + strstr(locale, "utf-8") || + strstr(locale, "UTF8") || + strstr(locale, "utf8"))) + treeType = TREE_TYPE_UTF8; + else + treeType = TREE_TYPE_ASCII; +#else + treeType = TREE_TYPE_ASCII; +#endif + } + switch (treeType) { + default: + case TREE_TYPE_ASCII: + pl->treeStr = ProcessList_treeStrAscii; + break; + case TREE_TYPE_UTF8: + pl->treeStr = ProcessList_treeStrUtf8; + break; + } + CRT_init(settings->delay, settings->colorScheme); -- cgit v1.2.3