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

flag, which requires libncursesw.
Thanks to Sergej Pupykin!
This commit is contained in:
Hisham Muhammad 2008-03-09 02:33:23 +00:00
parent fa87ff0251
commit 8fa33dc336
13 changed files with 174 additions and 50 deletions

View File

@ -1,6 +1,9 @@
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

View File

@ -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 \

View File

@ -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) {
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) {
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;

View File

@ -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>

14
Panel.c
View File

@ -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) {
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) {
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;

View File

@ -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) {
} }
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);
} }
} }

View File

@ -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"

View File

@ -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]);

View File

@ -1,12 +1,20 @@
#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 @@
#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,14 +48,76 @@ 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);
for (int i = this->len, j = 0; i < last; i++, j++) {
memset(&this->chstr[i], 0, sizeof(this->chstr[i]));
this->chstr[i].chars[0] = data[j];
this->chstr[i].attr = attrs;
}
this->chstr[last].chars[0] = 0;
this->len = last;
}
inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
cchar_t* ch = this->chstr + start;
for (int i = start; i <= finish; i++) {
ch->attr = attrs;
ch++;
}
}
int RichString_findChar(RichString *this, char c, int start) {
wchar_t wc = btowc(c);
cchar_t* ch = this->chstr + start;
for (int i = start; i < this->len; i++) {
if (ch->chars[0] == wc)
return i;
ch++;
}
return -1;
}
#else
inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
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; this->chstr[i] = data_c[j] | attrs;
this->chstr[last] = 0; this->chstr[last] = 0;
this->len = last; 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++;
}
}
int RichString_findChar(RichString *this, char c, int start) {
chtype* ch = this->chstr + start;
for (int i = start; i < this->len; i++) {
if ((*ch & 0xff) == c)
return i;
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) { inline void RichString_append(RichString* this, int attrs, char* data) {
RichString_appendn(this, attrs, data, strlen(data)); RichString_appendn(this, attrs, data, strlen(data));
} }
@ -43,22 +127,6 @@ void RichString_write(RichString* this, int attrs, char* data) {
RichString_append(this, attrs, data); RichString_append(this, attrs, data);
} }
void RichString_setAttr(RichString *this, int attrs) {
chtype* ch = this->chstr;
for (int i = 0; i < this->len; i++) {
*ch = (*ch & 0xff) | attrs;
ch++;
}
}
void RichString_applyAttr(RichString *this, int attrs) {
chtype* ch = this->chstr;
for (int i = 0; i < this->len; i++) {
*ch |= attrs;
ch++;
}
}
RichString RichString_quickString(int attrs, char* data) { RichString RichString_quickString(int attrs, char* data) {
RichString str; RichString str;
RichString_initVal(str); RichString_initVal(str);

View File

@ -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 @@
#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,16 +49,30 @@ 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_appendn(RichString* this, int attrs, char* data_c, int len);
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);
extern void RichString_append(RichString* this, int attrs, char* data); extern void RichString_append(RichString* this, int attrs, char* data);
void RichString_write(RichString* this, int attrs, char* data); void RichString_write(RichString* this, int attrs, char* data);
void RichString_setAttr(RichString *this, int attrs);
void RichString_applyAttr(RichString *this, int attrs);
RichString RichString_quickString(int attrs, char* data); RichString RichString_quickString(int attrs, char* data);
#endif #endif

View File

@ -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
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.))

7
htop.c
View File

@ -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) {
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")) {

1
htop.h
View File

@ -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"