Commit 8fa33dc3 authored by Hisham Muhammad's avatar Hisham Muhammad
Browse files

Add Unicode support, enabled with the --enable-unicode

flag, which requires libncursesw.
Thanks to Sergej Pupykin!
parent fa87ff02
What's new in version 0.7.1 What's new in version 0.7.1
* Add Unicode support, enabled with the --enable-unicode
flag, which requires libncursesw.
(thanks to Sergej Pupykin)
* BUGFIX: Fix display of CPU count for threaded processes. * BUGFIX: Fix display of CPU count for threaded processes.
When user threads are hidden, process now shows the When user threads are hidden, process now shows the
sum of processor usage for all processors. When user sum of processor usage for all processors. When user
......
...@@ -10,7 +10,7 @@ applications_DATA = htop.desktop ...@@ -10,7 +10,7 @@ applications_DATA = htop.desktop
pixmapdir = $(datadir)/pixmaps pixmapdir = $(datadir)/pixmaps
pixmap_DATA = htop.png pixmap_DATA = htop.png
htop_CFLAGS = -pedantic -Wall -std=c99 htop_CFLAGS = -pedantic -Wall -std=c99 -D_XOPEN_SOURCE_EXTENDED
AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \ myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \
......
...@@ -18,6 +18,7 @@ in the source distribution for its full text. ...@@ -18,6 +18,7 @@ in the source distribution for its full text.
#include "ListItem.h" #include "ListItem.h"
#include "String.h" #include "String.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
...@@ -266,7 +267,7 @@ void TextMeterMode_draw(Meter* this, int x, int y, int w) { ...@@ -266,7 +267,7 @@ void TextMeterMode_draw(Meter* this, int x, int y, int w) {
Meter_displayToStringBuffer(this, buffer); Meter_displayToStringBuffer(this, buffer);
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]); mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
mvaddchstr(y, x, Meter_stringBuffer.chstr); RichString_printVal(Meter_stringBuffer, y, x);
} }
/* ---------- BarMeterMode ---------- */ /* ---------- BarMeterMode ---------- */
...@@ -418,7 +419,7 @@ void LEDMeterMode_draw(Meter* this, int x, int y, int w) { ...@@ -418,7 +419,7 @@ void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
mvaddstr(y+2, x, this->caption); mvaddstr(y+2, x, this->caption);
int xx = x + strlen(this->caption); int xx = x + strlen(this->caption);
for (int i = 0; i < Meter_stringBuffer.len; i++) { for (int i = 0; i < Meter_stringBuffer.len; i++) {
char c = Meter_stringBuffer.chstr[i]; char c = RichString_getCharVal(Meter_stringBuffer, i);
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
LEDMeterMode_drawDigit(xx, y, c-48); LEDMeterMode_drawDigit(xx, y, c-48);
xx += 4; xx += 4;
......
...@@ -21,6 +21,7 @@ in the source distribution for its full text. ...@@ -21,6 +21,7 @@ in the source distribution for its full text.
#include "ListItem.h" #include "ListItem.h"
#include "String.h" #include "String.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
......
...@@ -265,8 +265,8 @@ void Panel_draw(Panel* this, bool focus) { ...@@ -265,8 +265,8 @@ void Panel_draw(Panel* this, bool focus) {
attrset(attr); attrset(attr);
mvhline(y, x, ' ', this->w); mvhline(y, x, ' ', this->w);
if (scrollH < this->header.len) { if (scrollH < this->header.len) {
mvaddchnstr(y, x, this->header.chstr + scrollH, RichString_printoffnVal(this->header, y, x, scrollH,
MIN(this->header.len - scrollH, this->w)); MIN(this->header.len - scrollH, this->w));
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
y++; y++;
...@@ -289,12 +289,12 @@ void Panel_draw(Panel* this, bool focus) { ...@@ -289,12 +289,12 @@ void Panel_draw(Panel* this, bool focus) {
RichString_setAttr(&itemRef, highlight); RichString_setAttr(&itemRef, highlight);
mvhline(y + j, x+0, ' ', this->w); mvhline(y + j, x+0, ' ', this->w);
if (amt > 0) if (amt > 0)
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt); RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
} else { } else {
mvhline(y+j, x+0, ' ', this->w); mvhline(y+j, x+0, ' ', this->w);
if (amt > 0) if (amt > 0)
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt); RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
} }
} }
for (int i = y + (last - first); i < y + this->h; i++) for (int i = y + (last - first); i < y + this->h; i++)
...@@ -312,12 +312,14 @@ void Panel_draw(Panel* this, bool focus) { ...@@ -312,12 +312,14 @@ void Panel_draw(Panel* this, bool focus) {
newObj->display(newObj, &newRef); newObj->display(newObj, &newRef);
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w); mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
if (scrollH < oldRef.len) if (scrollH < oldRef.len)
mvaddchnstr(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + this->scrollH, MIN(oldRef.len - scrollH, this->w)); RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
this->scrollH, MIN(oldRef.len - scrollH, this->w));
attrset(highlight); attrset(highlight);
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w); mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
RichString_setAttr(&newRef, highlight); RichString_setAttr(&newRef, highlight);
if (scrollH < newRef.len) if (scrollH < newRef.len)
mvaddchnstr(y+this->selected - this->scrollV, x+0, newRef.chstr + this->scrollH, MIN(newRef.len - scrollH, this->w)); RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
this->scrollH, MIN(newRef.len - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
} }
this->oldSelected = this->selected; this->oldSelected = this->selected;
......
...@@ -11,6 +11,7 @@ in the source distribution for its full text. ...@@ -11,6 +11,7 @@ in the source distribution for its full text.
#include "CRT.h" #include "CRT.h"
#include "String.h" #include "String.h"
#include "Process.h" #include "Process.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
...@@ -265,23 +266,20 @@ static void Process_printTime(RichString* str, unsigned long t) { ...@@ -265,23 +266,20 @@ static void Process_printTime(RichString* str, unsigned long t) {
} }
static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) { static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
int start = str->len;
RichString_append(str, attr, this->comm);
if (this->pl->highlightBaseName) { if (this->pl->highlightBaseName) {
char* firstSpace = strchr(this->comm, ' '); int finish = str->len - 1;
if (firstSpace) { int space = RichString_findChar(str, ' ', start);
char* slash = firstSpace; if (space != -1)
while (slash > this->comm && *slash != '/') finish = space - 1;
slash--; for (;;) {
if (slash > this->comm) { int slash = RichString_findChar(str, '/', start);
slash++; if (slash == -1 || slash > finish)
RichString_appendn(str, attr, this->comm, slash - this->comm); break;
} start = slash + 1;
RichString_appendn(str, baseattr, slash, firstSpace - slash);
RichString_append(str, attr, firstSpace);
} else {
RichString_append(str, baseattr, this->comm);
} }
} else { RichString_setAttrn(str, baseattr, start, finish);
RichString_append(str, attr, this->comm);
} }
} }
......
...@@ -14,6 +14,7 @@ in the source distribution for its full text. ...@@ -14,6 +14,7 @@ in the source distribution for its full text.
#include "Object.h" #include "Object.h"
#include "CRT.h" #include "CRT.h"
#include "String.h" #include "String.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
......
...@@ -283,7 +283,7 @@ void ProcessList_invertSortOrder(ProcessList* this) { ...@@ -283,7 +283,7 @@ void ProcessList_invertSortOrder(ProcessList* this) {
RichString ProcessList_printHeader(ProcessList* this) { RichString ProcessList_printHeader(ProcessList* this) {
RichString out; RichString out;
RichString_init(&out); RichString_initVal(out);
ProcessField* fields = this->fields; ProcessField* fields = this->fields;
for (int i = 0; fields[i]; i++) { for (int i = 0; fields[i]; i++) {
char* field = Process_printField(fields[i]); char* field = Process_printField(fields[i]);
......
#include "RichString.h" #include "RichString.h"
#ifndef CONFIG_H
#define CONFIG_H
#include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <curses.h> #include <curses.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <wchar.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
...@@ -15,9 +23,23 @@ ...@@ -15,9 +23,23 @@
#define RichString_init(this) (this)->len = 0 #define RichString_init(this) (this)->len = 0
#define RichString_initVal(this) (this).len = 0 #define RichString_initVal(this) (this).len = 0
#ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i])
#endif
typedef struct RichString_ { typedef struct RichString_ {
int len; int len;
#ifdef HAVE_LIBNCURSESW
cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1]; chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
}*/ }*/
...@@ -26,37 +48,83 @@ typedef struct RichString_ { ...@@ -26,37 +48,83 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
inline void RichString_appendn(RichString* this, int attrs, char* data, int len) { #ifdef HAVE_LIBNCURSESW
inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
wchar_t data[RICHSTRING_MAXLEN];
len = mbstowcs(data, data_c, RICHSTRING_MAXLEN);
if (len<0)
return;
int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len); int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
for (int i = this->len, j = 0; i < last; i++, j++) for (int i = this->len, j = 0; i < last; i++, j++) {
this->chstr[i] = data[j] | attrs; memset(&this->chstr[i], 0, sizeof(this->chstr[i]));
this->chstr[last] = 0; this->chstr[i].chars[0] = data[j];
this->chstr[i].attr = attrs;
}
this->chstr[last].chars[0] = 0;
this->len = last; this->len = last;
} }
inline void RichString_append(RichString* this, int attrs, char* data) { inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
RichString_appendn(this, attrs, data, strlen(data)); cchar_t* ch = this->chstr + start;
for (int i = start; i <= finish; i++) {
ch->attr = attrs;
ch++;
}
} }
void RichString_write(RichString* this, int attrs, char* data) { int RichString_findChar(RichString *this, char c, int start) {
RichString_init(this); wchar_t wc = btowc(c);
RichString_append(this, attrs, data); cchar_t* ch = this->chstr + start;
for (int i = start; i < this->len; i++) {
if (ch->chars[0] == wc)
return i;
ch++;
}
return -1;
} }
void RichString_setAttr(RichString *this, int attrs) { #else
chtype* ch = this->chstr;
for (int i = 0; i < this->len; i++) { inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
for (int i = this->len, j = 0; i < last; i++, j++)
this->chstr[i] = data_c[j] | attrs;
this->chstr[last] = 0;
this->len = last;
}
void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
chtype* ch = this->chstr + start;
for (int i = start; i <= finish; i++) {
*ch = (*ch & 0xff) | attrs; *ch = (*ch & 0xff) | attrs;
ch++; ch++;
} }
} }
void RichString_applyAttr(RichString *this, int attrs) { int RichString_findChar(RichString *this, char c, int start) {
chtype* ch = this->chstr; chtype* ch = this->chstr + start;
for (int i = 0; i < this->len; i++) { for (int i = start; i < this->len; i++) {
*ch |= attrs; if ((*ch & 0xff) == c)
return i;
ch++; ch++;
} }
return -1;
}
#endif
void RichString_setAttr(RichString *this, int attrs) {
RichString_setAttrn(this, attrs, 0, this->len - 1);
}
inline void RichString_append(RichString* this, int attrs, char* data) {
RichString_appendn(this, attrs, data, strlen(data));
}
void RichString_write(RichString* this, int attrs, char* data) {
RichString_init(this);
RichString_append(this, attrs, data);
} }
RichString RichString_quickString(int attrs, char* data) { RichString RichString_quickString(int attrs, char* data) {
......
...@@ -4,12 +4,20 @@ ...@@ -4,12 +4,20 @@
#define HEADER_RichString #define HEADER_RichString
#ifndef CONFIG_H
#define CONFIG_H
#include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <curses.h> #include <curses.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <wchar.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
...@@ -17,9 +25,23 @@ ...@@ -17,9 +25,23 @@
#define RichString_init(this) (this)->len = 0 #define RichString_init(this) (this)->len = 0
#define RichString_initVal(this) (this).len = 0 #define RichString_initVal(this) (this).len = 0
#ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i])
#endif
typedef struct RichString_ { typedef struct RichString_ {
int len; int len;
#ifdef HAVE_LIBNCURSESW
cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1]; chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
...@@ -27,15 +49,29 @@ typedef struct RichString_ { ...@@ -27,15 +49,29 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
extern void RichString_appendn(RichString* this, int attrs, char* data, int len); #ifdef HAVE_LIBNCURSESW
extern void RichString_append(RichString* this, int attrs, char* data); extern void RichString_appendn(RichString* this, int attrs, char* data_c, int len);
void RichString_write(RichString* this, int attrs, char* data); extern void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start);
#else
extern void RichString_appendn(RichString* this, int attrs, char* data_c, int len);
void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start);
#endif
void RichString_setAttr(RichString *this, int attrs); void RichString_setAttr(RichString *this, int attrs);
void RichString_applyAttr(RichString *this, int attrs); extern void RichString_append(RichString* this, int attrs, char* data);
void RichString_write(RichString* this, int attrs, char* data);
RichString RichString_quickString(int attrs, char* data); RichString RichString_quickString(int attrs, char* data);
......
...@@ -16,7 +16,6 @@ AM_ENABLE_STATIC ...@@ -16,7 +16,6 @@ AM_ENABLE_STATIC
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
# Checks for libraries. # Checks for libraries.
AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"])
AC_CHECK_LIB([m], [ceil], [], [missing_libraries="$missing_libraries libm"]) AC_CHECK_LIB([m], [ceil], [], [missing_libraries="$missing_libraries libm"])
if test ! -z "$missing_libraries"; then if test ! -z "$missing_libraries"; then
...@@ -67,7 +66,14 @@ AC_ARG_WITH(proc, [ --with-proc=DIR Location of a Linux-compatible proc fi ...@@ -67,7 +66,14 @@ AC_ARG_WITH(proc, [ --with-proc=DIR Location of a Linux-compatible proc fi
AC_ARG_ENABLE(openvz, [AC_HELP_STRING([--enable-openvz], [enable OpenVZ support])], ,enable_openvz="no") AC_ARG_ENABLE(openvz, [AC_HELP_STRING([--enable-openvz], [enable OpenVZ support])], ,enable_openvz="no")
if test "x$enable_openvz" = xyes; then if test "x$enable_openvz" = xyes; then
AC_DEFINE(HAVE_OPENVZ, 1, [Define if openvz support enabled.]) AC_DEFINE(HAVE_OPENVZ, 1, [Define if openvz support enabled.])
fi
AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="no")
if test "x$enable_unicode" = xyes; then
AC_CHECK_LIB([ncursesw], [refresh], [], [missing_libraries="$missing_libraries libncursesw"])
else
AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"])
fi fi
AC_CHECK_FILE($PROCDIR/stat,,AC_MSG_ERROR(Cannot find /proc/stat. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) AC_CHECK_FILE($PROCDIR/stat,,AC_MSG_ERROR(Cannot find /proc/stat. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.))
......
...@@ -11,6 +11,7 @@ in the source distribution for its full text. ...@@ -11,6 +11,7 @@ in the source distribution for its full text.
#include <sys/param.h> #include <sys/param.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h> #include <stdbool.h>
#include <locale.h>
#include "ProcessList.h" #include "ProcessList.h"
#include "CRT.h" #include "CRT.h"
...@@ -221,6 +222,12 @@ int main(int argc, char** argv) { ...@@ -221,6 +222,12 @@ int main(int argc, char** argv) {
uid_t userId = 0; uid_t userId = 0;
int sortKey = 0; int sortKey = 0;
char *lc_ctype = getenv("LC_CTYPE");
if(lc_ctype != NULL)
setlocale(LC_CTYPE, lc_ctype);
else
setlocale(LC_CTYPE, getenv("LC_ALL"));
int arg = 1; int arg = 1;
while (arg < argc) { while (arg < argc) {
if (String_eq(argv[arg], "--help")) { if (String_eq(argv[arg], "--help")) {
......
...@@ -15,6 +15,7 @@ in the source distribution for its full text. ...@@ -15,6 +15,7 @@ in the source distribution for its full text.
#include <sys/param.h> #include <sys/param.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h> #include <stdbool.h>
#include <locale.h>
#include "ProcessList.h" #include "ProcessList.h"
#include "CRT.h" #include "CRT.h"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment