1 Commits
1.0.3 ... 0.8

Author SHA1 Message Date
33fee7963a Tag release 0.8 in revision history. 2008-05-07 23:06:27 +00:00
121 changed files with 6419 additions and 6463 deletions

View File

@ -1,42 +0,0 @@
/*
htop - Affinity.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Affinity.h"
#include <stdlib.h>
/*{
typedef struct Affinity_ {
int size;
int used;
int* cpus;
} Affinity;
}*/
Affinity* Affinity_new() {
Affinity* this = calloc(1, sizeof(Affinity));
this->size = 8;
this->cpus = calloc(this->size, sizeof(int));
return this;
}
void Affinity_delete(Affinity* this) {
free(this->cpus);
free(this);
}
void Affinity_add(Affinity* this, int id) {
if (this->used == this->size) {
this->size *= 2;
this->cpus = realloc(this->cpus, sizeof(int) * this->size);
}
this->cpus[this->used] = id;
this->used++;
}

View File

@ -1,27 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Affinity
#define HEADER_Affinity
/*
htop - Affinity.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
typedef struct Affinity_ {
int size;
int used;
int* cpus;
} Affinity;
Affinity* Affinity_new();
void Affinity_delete(Affinity* this);
void Affinity_add(Affinity* this, int id);
#endif

View File

@ -1,74 +1,49 @@
/*
htop - AffinityPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "AffinityPanel.h" #include "AffinityPanel.h"
#include "Panel.h"
#include "CheckItem.h" #include "CheckItem.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <string.h>
/*{
#include "Panel.h"
#include "Affinity.h"
#include "ProcessList.h"
#include "ListItem.h"
}*/
static HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) { static HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) {
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) Panel_getSelected(this); CheckItem* selected = (CheckItem*) Panel_getSelected(this);
switch(ch) { switch(ch) {
case KEY_MOUSE: case KEY_MOUSE:
case ' ': case ' ':
CheckItem_set(selected, ! (CheckItem_get(selected)) ); CheckItem_set(selected, ! (CheckItem_get(selected)) );
return HANDLED; result = HANDLED;
break;
case 0x0a: case 0x0a:
case 0x0d: case 0x0d:
case KEY_ENTER: case KEY_ENTER:
return BREAK_LOOP; result = BREAK_LOOP;
break;
} }
return IGNORED; return result;
} }
PanelClass AffinityPanel_class = { Panel* AffinityPanel_new(int processorCount, unsigned long mask) {
.super = { Panel* this = Panel_new(1, 1, 1, 1, CHECKITEM_CLASS, true, ListItem_compare);
.extends = Class(Panel), this->eventHandler = AffinityPanel_eventHandler;
.delete = Panel_delete
},
.eventHandler = AffinityPanel_eventHandler
};
Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity) {
Panel* this = Panel_new(1, 1, 1, 1, true, Class(CheckItem));
Object_setClass(this, Class(AffinityPanel));
Panel_setHeader(this, "Use CPUs:"); Panel_setHeader(this, "Use CPUs:");
int curCpu = 0; for (int i = 0; i < processorCount; i++) {
for (int i = 0; i < pl->cpuCount; i++) {
char number[10]; char number[10];
snprintf(number, 9, "%d", ProcessList_cpuId(pl, i)); snprintf(number, 9, "%d", i+1);
bool mode; Panel_add(this, (Object*) CheckItem_new(String_copy(number), NULL, mask & (1 << i)));
if (curCpu < affinity->used && affinity->cpus[curCpu] == i) {
mode = true;
curCpu++;
} else {
mode = false;
}
Panel_add(this, (Object*) CheckItem_new(strdup(number), NULL, mode));
} }
return this; return this;
} }
Affinity* AffinityPanel_getAffinity(Panel* this) { unsigned long AffinityPanel_getAffinity(Panel* this) {
Affinity* affinity = Affinity_new(); int size = Panel_getSize(this);
int size = Panel_size(this); unsigned long mask = 0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if (CheckItem_get((CheckItem*)Panel_get(this, i))) if (CheckItem_get((CheckItem*)Panel_get(this, i)))
Affinity_add(affinity, i); mask = mask | (1 << i);
} }
return affinity; return mask;
} }

View File

@ -2,22 +2,16 @@
#ifndef HEADER_AffinityPanel #ifndef HEADER_AffinityPanel
#define HEADER_AffinityPanel #define HEADER_AffinityPanel
/*
htop - AffinityPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h" #include "Panel.h"
#include "Affinity.h" #include "CheckItem.h"
#include "ProcessList.h"
#include "ListItem.h"
extern PanelClass AffinityPanel_class; #include "debug.h"
#include <assert.h>
Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity); Panel* AffinityPanel_new(int processorCount, unsigned long mask);
Affinity* AffinityPanel_getAffinity(Panel* this); unsigned long AffinityPanel_getAffinity(Panel* this);
#endif #endif

View File

@ -1,23 +1,16 @@
/*
htop - AvailableColumnsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "AvailableColumnsPanel.h" #include "AvailableColumnsPanel.h"
#include "Settings.h"
#include "Header.h" #include "Header.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h" #include "ColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <ctype.h>
/*{ /*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct AvailableColumnsPanel_ { typedef struct AvailableColumnsPanel_ {
Panel super; Panel super;
@ -53,31 +46,19 @@ static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
result = HANDLED; result = HANDLED;
break; break;
} }
default:
{
if (isalpha(ch))
result = Panel_selectByTyping(super, ch);
break;
}
} }
return result; return result;
} }
PanelClass AvailableColumnsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = AvailableColumnsPanel_delete
},
.eventHandler = AvailableColumnsPanel_eventHandler
};
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr) { AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr) {
AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel); AvailableColumnsPanel* this = (AvailableColumnsPanel*) malloc(sizeof(AvailableColumnsPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true); Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableColumnsPanel_delete;
this->settings = settings; this->settings = settings;
this->scr = scr; this->scr = scr;
super->eventHandler = AvailableColumnsPanel_eventHandler;
Panel_setHeader(super, "Available Columns"); Panel_setHeader(super, "Available Columns");

View File

@ -2,16 +2,17 @@
#ifndef HEADER_AvailableColumnsPanel #ifndef HEADER_AvailableColumnsPanel
#define HEADER_AvailableColumnsPanel #define HEADER_AvailableColumnsPanel
/*
htop - AvailableColumnsPanel.h #include "Settings.h"
(C) 2004-2011 Hisham H. Muhammad #include "Header.h"
Released under the GNU GPL, see the COPYING file #include "ScreenManager.h"
in the source distribution for its full text. #include "ColumnsPanel.h"
*/
#include "Panel.h" #include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h" #include "debug.h"
#include <assert.h>
typedef struct AvailableColumnsPanel_ { typedef struct AvailableColumnsPanel_ {
Panel super; Panel super;
@ -22,8 +23,6 @@ typedef struct AvailableColumnsPanel_ {
} AvailableColumnsPanel; } AvailableColumnsPanel;
extern PanelClass AvailableColumnsPanel_class;
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr); AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr);
#endif #endif

View File

@ -1,23 +1,16 @@
/*
htop - AvailableMetersPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "AvailableMetersPanel.h" #include "AvailableMetersPanel.h"
#include "Settings.h"
#include "CPUMeter.h"
#include "Header.h" #include "Header.h"
#include "ListItem.h" #include "ScreenManager.h"
#include "CPUMeter.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
/*{ /*{
#include "Settings.h"
#include "Panel.h"
#include "ScreenManager.h"
typedef struct AvailableMetersPanel_ { typedef struct AvailableMetersPanel_ {
Panel super; Panel super;
@ -37,7 +30,7 @@ static void AvailableMetersPanel_delete(Object* object) {
free(this); free(this);
} }
static inline void AvailableMetersPanel_addHeader(Header* header, Panel* panel, MeterClass* type, int param, HeaderSide side) { static inline void AvailableMetersPanel_addHeader(Header* header, Panel* panel, MeterType* type, int param, HeaderSide side) {
Meter* meter = (Meter*) Header_addMeter(header, type, param, side); Meter* meter = (Meter*) Header_addMeter(header, type, param, side);
Panel_add(panel, (Object*) Meter_toListItem(meter)); Panel_add(panel, (Object*) Meter_toListItem(meter));
} }
@ -78,36 +71,30 @@ static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
return result; return result;
} }
PanelClass AvailableMetersPanel_class = {
.super = {
.extends = Class(Panel),
.delete = AvailableMetersPanel_delete
},
.eventHandler = AvailableMetersPanel_eventHandler
};
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr) { AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr) {
AvailableMetersPanel* this = AllocThis(AvailableMetersPanel); AvailableMetersPanel* this = (AvailableMetersPanel*) malloc(sizeof(AvailableMetersPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true); Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableMetersPanel_delete;
this->settings = settings; this->settings = settings;
this->leftPanel = leftMeters; this->leftPanel = leftMeters;
this->rightPanel = rightMeters; this->rightPanel = rightMeters;
this->scr = scr; this->scr = scr;
super->eventHandler = AvailableMetersPanel_eventHandler;
Panel_setHeader(super, "Available meters"); Panel_setHeader(super, "Available meters");
for (int i = 1; Meter_types[i]; i++) { for (int i = 1; Meter_types[i]; i++) {
MeterClass* type = Meter_types[i]; MeterType* type = Meter_types[i];
if (type != &CPUMeter_class) { if (type != &CPUMeter) {
Panel_add(super, (Object*) ListItem_new(type->uiName, i << 16)); Panel_add(super, (Object*) ListItem_new(type->uiName, i << 16));
} }
} }
MeterClass* type = &CPUMeter_class; MeterType* type = &CPUMeter;
int cpus = settings->pl->cpuCount; int processors = settings->pl->processorCount;
if (cpus > 1) { if (processors > 1) {
Panel_add(super, (Object*) ListItem_new("CPU average", 0)); Panel_add(super, (Object*) ListItem_new("CPU average", 0));
for (int i = 1; i <= cpus; i++) { for (int i = 1; i <= processors; i++) {
char buffer[50]; char buffer[50];
sprintf(buffer, "%s %d", type->uiName, i); sprintf(buffer, "%s %d", type->uiName, i);
Panel_add(super, (Object*) ListItem_new(buffer, i)); Panel_add(super, (Object*) ListItem_new(buffer, i));

View File

@ -2,16 +2,17 @@
#ifndef HEADER_AvailableMetersPanel #ifndef HEADER_AvailableMetersPanel
#define HEADER_AvailableMetersPanel #define HEADER_AvailableMetersPanel
/*
htop - AvailableMetersPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Settings.h" #include "Settings.h"
#include "Panel.h" #include "Header.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "CPUMeter.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableMetersPanel_ { typedef struct AvailableMetersPanel_ {
Panel super; Panel super;
@ -23,8 +24,6 @@ typedef struct AvailableMetersPanel_ {
} AvailableMetersPanel; } AvailableMetersPanel;
extern PanelClass AvailableMetersPanel_class;
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr); AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr);
#endif #endif

View File

@ -1,336 +0,0 @@
/*
htop - BatteryMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
*/
#include "BatteryMeter.h"
#include "ProcessList.h"
#include "CRT.h"
#include "String.h"
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
/*{
#include "Meter.h"
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
}*/
int BatteryMeter_attributes[] = {
BATTERY
};
static unsigned long int parseUevent(FILE * file, const char *key) {
char line[100];
unsigned long int dValue = 0;
char* saveptr;
while (fgets(line, sizeof line, file)) {
if (strncmp(line, key, strlen(key)) == 0) {
char *value;
strtok_r(line, "=", &saveptr);
value = strtok_r(NULL, "=", &saveptr);
dValue = atoi(value);
break;
}
}
return dValue;
}
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
const char batteryPath[] = PROCDIR "/acpi/battery/";
DIR* batteryDir = opendir(batteryPath);
if (!batteryDir)
return 0;
#define MAX_BATTERIES 64
char* batteries[MAX_BATTERIES];
unsigned int nBatteries = 0;
memset(batteries, 0, MAX_BATTERIES * sizeof(char*));
struct dirent result;
struct dirent* dirEntry;
while (nBatteries < MAX_BATTERIES) {
int err = readdir_r(batteryDir, &result, &dirEntry);
if (err || !dirEntry)
break;
char* entryName = dirEntry->d_name;
if (strncmp(entryName, "BAT", 3))
continue;
batteries[nBatteries] = strdup(entryName);
nBatteries++;
}
closedir(batteryDir);
unsigned long int total = 0;
for (unsigned int i = 0; i < nBatteries; i++) {
char infoPath[30];
snprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName);
FILE* file = fopen(infoPath, "r");
if (!file) {
break;
}
char line[50] = "";
for (unsigned short int i = 0; i < lineNum; i++) {
char* ok = fgets(line, sizeof line, file);
if (!ok) break;
}
fclose(file);
char *foundNumStr = String_getToken(line, wordNum);
const unsigned long int foundNum = atoi(foundNumStr);
free(foundNumStr);
total += foundNum;
}
for (unsigned int i = 0; i < nBatteries; i++) {
free(batteries[i]);
}
return total;
}
static ACPresence procAcpiCheck() {
ACPresence isOn = AC_ERROR;
const char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
DIR *power_supplyDir = opendir(power_supplyPath);
if (!power_supplyDir) {
return AC_ERROR;
}
struct dirent result;
struct dirent* dirEntry;
for (;;) {
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
if (err || !dirEntry)
break;
char* entryName = (char *) dirEntry->d_name;
if (entryName[0] != 'A')
continue;
char statePath[50];
snprintf((char *) statePath, sizeof statePath, "%s/%s/state", power_supplyPath, entryName);
FILE* file = fopen(statePath, "r");
if (!file) {
isOn = AC_ERROR;
continue;
}
char line[100];
fgets(line, sizeof line, file);
line[sizeof(line) - 1] = '\0';
fclose(file);
const char *isOnline = String_getToken(line, 2);
if (strcmp(isOnline, "on-line") == 0) {
isOn = AC_PRESENT;
} else {
isOn = AC_ABSENT;
}
free((char *) isOnline);
if (isOn == AC_PRESENT) {
break;
}
}
if (power_supplyDir)
closedir(power_supplyDir);
return isOn;
}
static ACPresence sysCheck() {
ACPresence isOn = AC_ERROR;
const char *power_supplyPath = "/sys/class/power_supply";
DIR *power_supplyDir = opendir(power_supplyPath);
if (!power_supplyDir) {
return AC_ERROR;
}
struct dirent result;
struct dirent* dirEntry;
for (;;) {
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
if (err || !dirEntry)
break;
char* entryName = (char *) dirEntry->d_name;
if (strncmp(entryName, "A", 1)) {
continue;
}
char onlinePath[50];
snprintf((char *) onlinePath, sizeof onlinePath, "%s/%s/online", power_supplyPath, entryName);
FILE* file = fopen(onlinePath, "r");
if (!file) {
isOn = AC_ERROR;
} else {
isOn = (fgetc(file) - '0');
fclose(file);
if (isOn == AC_PRESENT) {
// If any AC adapter is being used then stop
break;
}
}
}
if (power_supplyDir)
closedir(power_supplyDir);
return isOn;
}
static ACPresence chkIsOnline() {
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
return procAcpiCheck();
} else if (access("/sys/class/power_supply", F_OK) == 0) {
return sysCheck();
} else {
return AC_ERROR;
}
}
static double getProcBatData() {
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
if (totalFull == 0)
return 0;
const unsigned long int totalRemain = parseBatInfo("state", 5, 3);
if (totalRemain == 0)
return 0;
return totalRemain * 100.0 / (double) totalFull;
}
static double getSysBatData() {
const char *power_supplyPath = "/sys/class/power_supply/";
DIR *power_supplyDir = opendir(power_supplyPath);
if (!power_supplyDir)
return 0;
unsigned long int totalFull = 0;
unsigned long int totalRemain = 0;
struct dirent result;
struct dirent* dirEntry;
for (;;) {
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
if (err || !dirEntry)
break;
char* entryName = (char *) dirEntry->d_name;
if (strncmp(entryName, "BAT", 3)) {
continue;
}
const char ueventPath[50];
snprintf((char *) ueventPath, sizeof ueventPath, "%s%s/uevent", power_supplyPath, entryName);
FILE *file;
if ((file = fopen(ueventPath, "r")) == NULL) {
closedir(power_supplyDir);
return 0;
}
if ((totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL="))) {
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
} else {
//reset file pointer
if (fseek(file, 0, SEEK_SET) < 0) {
closedir(power_supplyDir);
fclose(file);
return 0;
}
}
//Some systems have it as CHARGE instead of ENERGY.
if ((totalFull += parseUevent(file, "POWER_SUPPLY_CHARGE_FULL="))) {
totalRemain += parseUevent(file, "POWER_SUPPLY_CHARGE_NOW=");
} else {
//reset file pointer
if (fseek(file, 0, SEEK_SET) < 0) {
closedir(power_supplyDir);
fclose(file);
return 0;
}
}
fclose(file);
}
const double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
closedir(power_supplyDir);
return percent;
}
static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
double percent = getProcBatData();
if (percent == 0) {
percent = getSysBatData();
if (percent == 0) {
snprintf(buffer, len, "n/a");
return;
}
}
this->values[0] = percent;
const char *onAcText, *onBatteryText, *unknownText;
unknownText = "%.1f%%";
if (this->mode == TEXT_METERMODE) {
onAcText = "%.1f%% (Running on A/C)";
onBatteryText = "%.1f%% (Running on battery)";
} else {
onAcText = "%.1f%%(A/C)";
onBatteryText = "%.1f%%(bat)";
}
ACPresence isOnLine = chkIsOnline();
if (isOnLine == AC_PRESENT) {
snprintf(buffer, len, onAcText, percent);
} else if (isOnLine == AC_ABSENT) {
snprintf(buffer, len, onBatteryText, percent);
} else {
snprintf(buffer, len, unknownText, percent);
}
return;
}
MeterClass BatteryMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.setValues = BatteryMeter_setValues,
.defaultMode = TEXT_METERMODE,
.total = 100.0,
.attributes = BatteryMeter_attributes,
.name = "Battery",
.uiName = "Battery",
.caption = "Battery: "
};

View File

@ -1,27 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_BatteryMeter
#define HEADER_BatteryMeter
/*
htop - BatteryMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
*/
#include "Meter.h"
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
extern int BatteryMeter_attributes[];
extern MeterClass BatteryMeter_class;
#endif

17
COPYING
View File

@ -337,20 +337,3 @@ proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General library. If this is what you want to do, use the GNU Library General
Public License instead of this License. Public License instead of this License.
Appendix 2: Special exception concerning PLPA
In the following exception, "PLPA" means (i) code released by the
Portable Linux Processor Affinity Project, or (ii) derivative works of
such code, in both cases provided that the code is covered entirely by
free software licensing terms.
As a special exception to the GNU GPL, the licensors of htop give you
permission to combine GNU GPL-licensed code in htop (and derivative
works of such code) with PLPA. You may copy and distribute such a
combined work following the terms of the GNU GPL for htop and the
applicable licenses of the version of PLPA used in your combined work,
provided that you include the source code of such version of PLPA when
and as the GNU GPL requires distribution of source code.

View File

@ -1,26 +1,25 @@
/* /*
htop - CPUMeter.c htop - CPUMeter.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "CPUMeter.h" #include "CPUMeter.h"
#include "Meter.h"
#include "CRT.h"
#include "ProcessList.h" #include "ProcessList.h"
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <curses.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
/*{ #include "debug.h"
#include "Meter.h" #include <assert.h>
}*/
int CPUMeter_attributes[] = { int CPUMeter_attributes[] = {
CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, CPU_IOWAIT CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_IOWAIT
}; };
#ifndef MIN #ifndef MIN
@ -31,10 +30,10 @@ int CPUMeter_attributes[] = {
#endif #endif
static void CPUMeter_init(Meter* this) { static void CPUMeter_init(Meter* this) {
int cpu = this->param; int processor = this->param;
if (this->pl->cpuCount > 1) { if (this->pl->processorCount > 1) {
char caption[10]; char caption[10];
sprintf(caption, "%-3d", ProcessList_cpuId(this->pl, cpu - 1)); sprintf(caption, "%-3d", processor);
Meter_setCaption(this, caption); Meter_setCaption(this, caption);
} }
if (this->param == 0) if (this->param == 0)
@ -43,49 +42,31 @@ static void CPUMeter_init(Meter* this) {
static void CPUMeter_setValues(Meter* this, char* buffer, int size) { static void CPUMeter_setValues(Meter* this, char* buffer, int size) {
ProcessList* pl = this->pl; ProcessList* pl = this->pl;
int cpu = this->param; int processor = this->param;
if (cpu > this->pl->cpuCount) { double total = (double) pl->totalPeriod[processor];
snprintf(buffer, size, "absent"); double cpu;
return; this->values[0] = pl->nicePeriod[processor] / total * 100.0;
} this->values[1] = pl->userPeriod[processor] / total * 100.0;
CPUData* cpuData = &(pl->cpus[cpu]);
double total = (double) ( cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod);
double percent;
double* v = this->values;
v[0] = cpuData->nicePeriod / total * 100.0;
v[1] = cpuData->userPeriod / total * 100.0;
if (pl->detailedCPUTime) { if (pl->detailedCPUTime) {
v[2] = cpuData->systemPeriod / total * 100.0; this->values[2] = pl->systemPeriod[processor] / total * 100.0;
v[3] = cpuData->irqPeriod / total * 100.0; this->values[3] = pl->irqPeriod[processor] / total * 100.0;
v[4] = cpuData->softIrqPeriod / total * 100.0; this->values[4] = pl->softIrqPeriod[processor] / total * 100.0;
v[5] = cpuData->stealPeriod / total * 100.0; this->values[5] = pl->ioWaitPeriod[processor] / total * 100.0;
v[6] = cpuData->guestPeriod / total * 100.0; this->type->items = 6;
v[7] = cpuData->ioWaitPeriod / total * 100.0; cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2]+
Meter_setItems(this, 8); this->values[3]+this->values[4])));
if (pl->accountGuestInCPUMeter) {
percent = v[0]+v[1]+v[2]+v[3]+v[4]+v[5]+v[6];
} else { } else {
percent = v[0]+v[1]+v[2]+v[3]+v[4]; this->values[2] = pl->systemAllPeriod[processor] / total * 100.0;
this->type->items = 3;
cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2])));
} }
} else { snprintf(buffer, size, "%5.1f%%", cpu );
v[2] = cpuData->systemAllPeriod / total * 100.0;
v[3] = (cpuData->stealPeriod + cpuData->guestPeriod) / total * 100.0;
Meter_setItems(this, 4);
percent = v[0]+v[1]+v[2]+v[3];
}
percent = MIN(100.0, MAX(0.0, percent));
if (isnan(percent)) percent = 0.0;
snprintf(buffer, size, "%5.1f%%", percent);
} }
static void CPUMeter_display(Object* cast, RichString* out) { static void CPUMeter_display(Object* cast, RichString* out) {
char buffer[50]; char buffer[50];
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
RichString_prune(out); RichString_init(out);
if (this->param > this->pl->cpuCount) {
RichString_append(out, CRT_colors[METER_TEXT], "absent");
return;
}
sprintf(buffer, "%5.1f%% ", this->values[1]); sprintf(buffer, "%5.1f%% ", this->values[1]);
RichString_append(out, CRT_colors[METER_TEXT], ":"); RichString_append(out, CRT_colors[METER_TEXT], ":");
RichString_append(out, CRT_colors[CPU_NORMAL], buffer); RichString_append(out, CRT_colors[CPU_NORMAL], buffer);
@ -95,24 +76,14 @@ static void CPUMeter_display(Object* cast, RichString* out) {
RichString_append(out, CRT_colors[CPU_KERNEL], buffer); RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
sprintf(buffer, "%5.1f%% ", this->values[0]); sprintf(buffer, "%5.1f%% ", this->values[0]);
RichString_append(out, CRT_colors[METER_TEXT], "ni:"); RichString_append(out, CRT_colors[METER_TEXT], "ni:");
RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer); RichString_append(out, CRT_colors[CPU_NICE], buffer);
sprintf(buffer, "%5.1f%% ", this->values[3]); sprintf(buffer, "%5.1f%% ", this->values[3]);
RichString_append(out, CRT_colors[METER_TEXT], "hi:"); RichString_append(out, CRT_colors[METER_TEXT], "hi:");
RichString_append(out, CRT_colors[CPU_IRQ], buffer); RichString_append(out, CRT_colors[CPU_IRQ], buffer);
sprintf(buffer, "%5.1f%% ", this->values[4]); sprintf(buffer, "%5.1f%% ", this->values[4]);
RichString_append(out, CRT_colors[METER_TEXT], "si:"); RichString_append(out, CRT_colors[METER_TEXT], "si:");
RichString_append(out, CRT_colors[CPU_SOFTIRQ], buffer); RichString_append(out, CRT_colors[CPU_SOFTIRQ], buffer);
if (this->values[5]) {
sprintf(buffer, "%5.1f%% ", this->values[5]); sprintf(buffer, "%5.1f%% ", this->values[5]);
RichString_append(out, CRT_colors[METER_TEXT], "st:");
RichString_append(out, CRT_colors[CPU_STEAL], buffer);
}
if (this->values[6]) {
sprintf(buffer, "%5.1f%% ", this->values[6]);
RichString_append(out, CRT_colors[METER_TEXT], "gu:");
RichString_append(out, CRT_colors[CPU_GUEST], buffer);
}
sprintf(buffer, "%5.1f%% ", this->values[7]);
RichString_append(out, CRT_colors[METER_TEXT], "wa:"); RichString_append(out, CRT_colors[METER_TEXT], "wa:");
RichString_append(out, CRT_colors[CPU_IOWAIT], buffer); RichString_append(out, CRT_colors[CPU_IOWAIT], buffer);
} else { } else {
@ -121,114 +92,49 @@ static void CPUMeter_display(Object* cast, RichString* out) {
RichString_append(out, CRT_colors[CPU_KERNEL], buffer); RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
sprintf(buffer, "%5.1f%% ", this->values[0]); sprintf(buffer, "%5.1f%% ", this->values[0]);
RichString_append(out, CRT_colors[METER_TEXT], "low:"); RichString_append(out, CRT_colors[METER_TEXT], "low:");
RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer); RichString_append(out, CRT_colors[CPU_NICE], buffer);
if (this->values[3]) {
sprintf(buffer, "%5.1f%% ", this->values[3]);
RichString_append(out, CRT_colors[METER_TEXT], "vir:");
RichString_append(out, CRT_colors[CPU_GUEST], buffer);
}
}
}
static void AllCPUsMeter_getRange(Meter* this, int* start, int* count) {
int cpus = this->pl->cpuCount;
switch(Meter_name(this)[0]) {
default:
case 'A': // All
*start = 0;
*count = cpus;
break;
case 'L': // First Half
*start = 0;
*count = (cpus+1) / 2;
break;
case 'R': // Second Half
*start = (cpus+1) / 2;
*count = cpus / 2;
break;
} }
} }
static void AllCPUsMeter_init(Meter* this) { static void AllCPUsMeter_init(Meter* this) {
int cpus = this->pl->cpuCount; int processors = this->pl->processorCount;
if (!this->drawData) this->drawBuffer = malloc(sizeof(Meter*) * processors);
this->drawData = calloc(cpus, sizeof(Meter*)); Meter** meters = (Meter**) this->drawBuffer;
Meter** meters = (Meter**) this->drawData; for (int i = 0; i < processors; i++)
int start, count; meters[i] = Meter_new(this->pl, i+1, &CPUMeter);
AllCPUsMeter_getRange(this, &start, &count); this->h = processors;
for (int i = 0; i < count; i++) {
if (!meters[i])
meters[i] = Meter_new(this->pl, start+i+1, (MeterClass*) Class(CPUMeter));
Meter_init(meters[i]);
}
if (this->mode == 0)
this->mode = BAR_METERMODE; this->mode = BAR_METERMODE;
int h = Meter_modes[this->mode]->h;
if (strchr(Meter_name(this), '2'))
this->h = h * ((count+1) / 2);
else
this->h = h * count;
} }
static void AllCPUsMeter_done(Meter* this) { static void AllCPUsMeter_done(Meter* this) {
Meter** meters = (Meter**) this->drawData; int processors = this->pl->processorCount;
int start, count; Meter** meters = (Meter**) this->drawBuffer;
AllCPUsMeter_getRange(this, &start, &count); for (int i = 0; i < processors; i++)
for (int i = 0; i < count; i++)
Meter_delete((Object*)meters[i]); Meter_delete((Object*)meters[i]);
} }
static void AllCPUsMeter_updateMode(Meter* this, int mode) { static void AllCPUsMeter_setMode(Meter* this, int mode) {
Meter** meters = (Meter**) this->drawData;
this->mode = mode; this->mode = mode;
int h = Meter_modes[mode]->h; int processors = this->pl->processorCount;
int start, count; int h = Meter_modes[this->mode]->h;
AllCPUsMeter_getRange(this, &start, &count); this->h = h * processors;
for (int i = 0; i < count; i++) {
Meter_setMode(meters[i], mode);
}
if (strchr(Meter_name(this), '2'))
this->h = h * ((count+1) / 2);
else
this->h = h * count;
} }
static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) { static void AllCPUsMeter_draw(Meter* this, int x, int y, int w) {
Meter** meters = (Meter**) this->drawData; int processors = this->pl->processorCount;
int start, count; Meter** meters = (Meter**) this->drawBuffer;
AllCPUsMeter_getRange(this, &start, &count); for (int i = 0; i < processors; i++) {
int height = (count+1)/2; Meter_setMode(meters[i], this->mode);
int startY = y;
for (int i = 0; i < height; i++) {
meters[i]->draw(meters[i], x, y, (w-2)/2);
y += meters[i]->h;
}
y = startY;
for (int i = height; i < count; i++) {
meters[i]->draw(meters[i], x+(w-1)/2+2, y, (w-2)/2);
y += meters[i]->h;
}
}
static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) {
Meter** meters = (Meter**) this->drawData;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++) {
meters[i]->draw(meters[i], x, y, w); meters[i]->draw(meters[i], x, y, w);
y += meters[i]->h; y += meters[i]->h;
} }
} }
MeterClass CPUMeter_class = { MeterType CPUMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.setValues = CPUMeter_setValues, .setValues = CPUMeter_setValues,
.defaultMode = BAR_METERMODE, .display = CPUMeter_display,
.maxItems = 8, .mode = BAR_METERMODE,
.items = 6,
.total = 100.0, .total = 100.0,
.attributes = CPUMeter_attributes, .attributes = CPUMeter_attributes,
.name = "CPU", .name = "CPU",
@ -237,111 +143,16 @@ MeterClass CPUMeter_class = {
.init = CPUMeter_init .init = CPUMeter_init
}; };
MeterClass AllCPUsMeter_class = { MeterType AllCPUsMeter = {
.super = { .mode = 0,
.extends = Class(Meter), .items = 1,
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0, .total = 100.0,
.attributes = CPUMeter_attributes, .attributes = CPUMeter_attributes,
.name = "AllCPUs", .name = "AllCPUs",
.uiName = "CPUs (1/1)", .uiName = "All CPUs",
.caption = "CPU", .caption = "CPU",
.draw = SingleColCPUsMeter_draw, .draw = AllCPUsMeter_draw,
.init = AllCPUsMeter_init, .init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode, .setMode = AllCPUsMeter_setMode,
.done = AllCPUsMeter_done .done = AllCPUsMeter_done
}; };
MeterClass AllCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs2",
.uiName = "CPUs (1&2/2)",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass LeftCPUsMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs",
.uiName = "CPUs (1/2)",
.caption = "CPU",
.draw = SingleColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass RightCPUsMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs",
.uiName = "CPUs (2/2)",
.caption = "CPU",
.draw = SingleColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass LeftCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs2",
.uiName = "CPUs (1&2/4)",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass RightCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs2",
.uiName = "CPUs (3&4/4)",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};

View File

@ -4,13 +4,23 @@
#define HEADER_CPUMeter #define HEADER_CPUMeter
/* /*
htop - CPUMeter.h htop - CPUMeter.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include "debug.h"
#include <assert.h>
extern int CPUMeter_attributes[]; extern int CPUMeter_attributes[];
#ifndef MIN #ifndef MIN
@ -20,19 +30,8 @@ extern int CPUMeter_attributes[];
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
extern MeterClass CPUMeter_class; extern MeterType CPUMeter;
extern MeterClass AllCPUsMeter_class;
extern MeterClass AllCPUs2Meter_class;
extern MeterClass LeftCPUsMeter_class;
extern MeterClass RightCPUsMeter_class;
extern MeterClass LeftCPUs2Meter_class;
extern MeterClass RightCPUs2Meter_class;
extern MeterType AllCPUsMeter;
#endif #endif

164
CRT.c
View File

@ -1,24 +1,21 @@
/* /*
htop - CRT.c htop - CRT.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "CRT.h" #include "CRT.h"
#include "config.h" #include <curses.h>
#include "String.h"
#include "RichString.h"
#include <stdio.h>
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <stdbool.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h> #include "String.h"
#endif
#include "config.h"
#include "debug.h"
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j) #define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
@ -40,8 +37,9 @@ in the source distribution for its full text.
//#link curses //#link curses
bool CRT_hasColors;
/*{ /*{
#include <stdbool.h>
typedef enum ColorElements_ { typedef enum ColorElements_ {
RESET_COLOR, RESET_COLOR,
@ -58,7 +56,7 @@ typedef enum ColorElements_ {
METER_VALUE, METER_VALUE,
LED_COLOR, LED_COLOR,
UPTIME, UPTIME,
BATTERY, TASKS_TOTAL,
TASKS_RUNNING, TASKS_RUNNING,
SWAP, SWAP,
PROCESS, PROCESS,
@ -85,7 +83,6 @@ typedef enum ColorElements_ {
GRAPH_9, GRAPH_9,
MEMORY_USED, MEMORY_USED,
MEMORY_BUFFERS, MEMORY_BUFFERS,
MEMORY_BUFFERS_TEXT,
MEMORY_CACHE, MEMORY_CACHE,
LOAD, LOAD,
LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIFTEEN,
@ -95,67 +92,35 @@ typedef enum ColorElements_ {
CHECK_MARK, CHECK_MARK,
CHECK_TEXT, CHECK_TEXT,
CLOCK, CLOCK,
HELP_BOLD,
HOSTNAME,
CPU_NICE, CPU_NICE,
CPU_NICE_TEXT,
CPU_NORMAL, CPU_NORMAL,
CPU_KERNEL, CPU_KERNEL,
HELP_BOLD,
CPU_IOWAIT, CPU_IOWAIT,
CPU_IRQ, CPU_IRQ,
CPU_SOFTIRQ, CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
void CRT_fatalError(const char* note) __attribute__ ((noreturn));
}*/ }*/
// TODO: centralize these in Settings. // TODO: centralize these in Settings.
static bool CRT_hasColors; int CRT_delay = 0;
static int CRT_delay = 0;
int CRT_colorScheme = 0; int CRT_colorScheme = 0;
bool CRT_utf8 = false;
int CRT_colors[LAST_COLORELEMENT] = { 0 }; int CRT_colors[LAST_COLORELEMENT] = { 0 };
int CRT_cursorX = 0;
int CRT_scrollHAmount = 5;
char* CRT_termType; char* CRT_termType;
void *backtraceArray[128]; static void CRT_handleSIGSEGV(int signal) {
static void CRT_handleSIGSEGV(int sgn) {
(void) sgn;
CRT_done(); CRT_done();
#if __linux fprintf(stderr, "htop " VERSION " aborted. Please report bug at http://htop.sf.net\n");
fprintf(stderr, "\n\nhtop " VERSION " aborting. Please report bug at http://hisham.hm/htop\n"); exit(1);
#ifdef HAVE_EXECINFO_H
size_t size = backtrace(backtraceArray, sizeof(backtraceArray) / sizeof(void *));
fprintf(stderr, "\n Please include in your report the following backtrace: \n");
backtrace_symbols_fd(backtraceArray, size, 2);
fprintf(stderr, "\nAdditionally, in order to make the above backtrace useful,");
fprintf(stderr, "\nplease also run the following command to generate a disassembly of your binary:");
fprintf(stderr, "\n\n objdump -d `which htop` > ~/htop.objdump");
fprintf(stderr, "\n\nand then attach the file ~/htop.objdump to your bug report.");
fprintf(stderr, "\n\nThank you for helping to improve htop!\n\n");
#endif
#else
fprintf(stderr, "\n\nhtop " VERSION " aborting. Unsupported platform.\n");
#endif
abort();
} }
static void CRT_handleSIGTERM(int sgn) { static void CRT_handleSIGTERM(int signal) {
(void) sgn;
CRT_done(); CRT_done();
exit(0); exit(0);
} }
@ -167,7 +132,7 @@ void CRT_init(int delay, int colorScheme) {
noecho(); noecho();
CRT_delay = delay; CRT_delay = delay;
CRT_colorScheme = colorScheme; CRT_colorScheme = colorScheme;
halfdelay(CRT_delay/2); halfdelay(CRT_delay);
nonl(); nonl();
intrflush(stdscr, false); intrflush(stdscr, false);
keypad(stdscr, true); keypad(stdscr, true);
@ -179,15 +144,9 @@ void CRT_init(int delay, int colorScheme) {
CRT_hasColors = false; CRT_hasColors = false;
} }
CRT_termType = getenv("TERM"); CRT_termType = getenv("TERM");
if (String_eq(CRT_termType, "linux"))
CRT_scrollHAmount = 20;
else
CRT_scrollHAmount = 5;
if (String_eq(CRT_termType, "xterm") || String_eq(CRT_termType, "xterm-color") || String_eq(CRT_termType, "vt220")) { if (String_eq(CRT_termType, "xterm") || String_eq(CRT_termType, "xterm-color") || String_eq(CRT_termType, "vt220")) {
define_key("\033[H", KEY_HOME); define_key("\033[H", KEY_HOME);
define_key("\033[F", KEY_END); define_key("\033[F", KEY_END);
define_key("\033[7~", KEY_HOME);
define_key("\033[8~", KEY_END);
define_key("\033OP", KEY_F(1)); define_key("\033OP", KEY_F(1));
define_key("\033OQ", KEY_F(2)); define_key("\033OQ", KEY_F(2));
define_key("\033OR", KEY_F(3)); define_key("\033OR", KEY_F(3));
@ -215,19 +174,12 @@ void CRT_done() {
endwin(); endwin();
} }
void CRT_fatalError(const char* note) {
char* sysMsg = strerror(errno);
CRT_done();
fprintf(stderr, "%s: %s\n", note, sysMsg);
exit(2);
}
int CRT_readKey() { int CRT_readKey() {
nocbreak(); nocbreak();
cbreak(); cbreak();
nodelay(stdscr, FALSE); nodelay(stdscr, FALSE);
int ret = getch(); int ret = getch();
halfdelay(CRT_delay/2); halfdelay(CRT_delay);
return ret; return ret;
} }
@ -238,7 +190,7 @@ void CRT_disableDelay() {
} }
void CRT_enableDelay() { void CRT_enableDelay() {
halfdelay(CRT_delay/2); halfdelay(CRT_delay);
} }
void CRT_setColors(int colorScheme) { void CRT_setColors(int colorScheme) {
@ -264,7 +216,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD; CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD;
CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD; CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD;
CRT_colors[UPTIME] = A_BOLD; CRT_colors[UPTIME] = A_BOLD;
CRT_colors[BATTERY] = A_BOLD;
CRT_colors[LARGE_NUMBER] = A_BOLD; CRT_colors[LARGE_NUMBER] = A_BOLD;
CRT_colors[METER_TEXT] = A_NORMAL; CRT_colors[METER_TEXT] = A_NORMAL;
CRT_colors[METER_VALUE] = A_BOLD; CRT_colors[METER_VALUE] = A_BOLD;
@ -295,27 +246,22 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = A_DIM; CRT_colors[GRAPH_9] = A_DIM;
CRT_colors[MEMORY_USED] = A_BOLD; CRT_colors[MEMORY_USED] = A_BOLD;
CRT_colors[MEMORY_BUFFERS] = A_NORMAL; CRT_colors[MEMORY_BUFFERS] = A_NORMAL;
CRT_colors[MEMORY_BUFFERS_TEXT] = A_NORMAL;
CRT_colors[MEMORY_CACHE] = A_NORMAL; CRT_colors[MEMORY_CACHE] = A_NORMAL;
CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM; CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM;
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL;
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD; CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD;
CRT_colors[LOAD] = A_BOLD; CRT_colors[LOAD] = A_BOLD;
CRT_colors[HELP_BOLD] = A_BOLD; CRT_colors[HELP_BOLD] = A_BOLD;
CRT_colors[CPU_NICE] = A_NORMAL;
CRT_colors[CPU_NORMAL] = A_BOLD;
CRT_colors[CPU_KERNEL] = A_BOLD;
CRT_colors[CLOCK] = A_BOLD; CRT_colors[CLOCK] = A_BOLD;
CRT_colors[CHECK_BOX] = A_BOLD; CRT_colors[CHECK_BOX] = A_BOLD;
CRT_colors[CHECK_MARK] = A_NORMAL; CRT_colors[CHECK_MARK] = A_NORMAL;
CRT_colors[CHECK_TEXT] = A_NORMAL; CRT_colors[CHECK_TEXT] = A_NORMAL;
CRT_colors[HOSTNAME] = A_BOLD;
CRT_colors[CPU_NICE] = A_NORMAL;
CRT_colors[CPU_NICE_TEXT] = A_NORMAL;
CRT_colors[CPU_NORMAL] = A_BOLD;
CRT_colors[CPU_KERNEL] = A_BOLD;
CRT_colors[CPU_IOWAIT] = A_NORMAL; CRT_colors[CPU_IOWAIT] = A_NORMAL;
CRT_colors[CPU_IRQ] = A_BOLD; CRT_colors[CPU_IRQ] = A_BOLD;
CRT_colors[CPU_SOFTIRQ] = A_BOLD; CRT_colors[CPU_SOFTIRQ] = A_BOLD;
CRT_colors[CPU_STEAL] = A_REVERSE;
CRT_colors[CPU_GUEST] = A_REVERSE;
} else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE) { } else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE) {
CRT_colors[RESET_COLOR] = ColorPair(Black,White); CRT_colors[RESET_COLOR] = ColorPair(Black,White);
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,White); CRT_colors[DEFAULT_COLOR] = ColorPair(Black,White);
@ -327,7 +273,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Yellow,White); CRT_colors[UPTIME] = ColorPair(Yellow,White);
CRT_colors[BATTERY] = ColorPair(Yellow,White);
CRT_colors[LARGE_NUMBER] = ColorPair(Red,White); CRT_colors[LARGE_NUMBER] = ColorPair(Red,White);
CRT_colors[METER_TEXT] = ColorPair(Blue,White); CRT_colors[METER_TEXT] = ColorPair(Blue,White);
CRT_colors[METER_VALUE] = ColorPair(Black,White); CRT_colors[METER_VALUE] = ColorPair(Black,White);
@ -358,27 +303,22 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = ColorPair(Yellow,White); CRT_colors[GRAPH_9] = ColorPair(Yellow,White);
CRT_colors[MEMORY_USED] = ColorPair(Green,White); CRT_colors[MEMORY_USED] = ColorPair(Green,White);
CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White); CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White);
CRT_colors[MEMORY_BUFFERS_TEXT] = ColorPair(Cyan,White);
CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White);
CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White);
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White);
CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,White); CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,White);
CRT_colors[LOAD] = ColorPair(Black,White); CRT_colors[LOAD] = ColorPair(Black,White);
CRT_colors[HELP_BOLD] = ColorPair(Blue,White); CRT_colors[HELP_BOLD] = ColorPair(Blue,White);
CRT_colors[CPU_NICE] = ColorPair(Cyan,White);
CRT_colors[CPU_NORMAL] = ColorPair(Green,White);
CRT_colors[CPU_KERNEL] = ColorPair(Red,White);
CRT_colors[CLOCK] = ColorPair(Black,White); CRT_colors[CLOCK] = ColorPair(Black,White);
CRT_colors[CHECK_BOX] = ColorPair(Blue,White); CRT_colors[CHECK_BOX] = ColorPair(Blue,White);
CRT_colors[CHECK_MARK] = ColorPair(Black,White); CRT_colors[CHECK_MARK] = ColorPair(Black,White);
CRT_colors[CHECK_TEXT] = ColorPair(Black,White); CRT_colors[CHECK_TEXT] = ColorPair(Black,White);
CRT_colors[HOSTNAME] = ColorPair(Black,White); CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black);
CRT_colors[CPU_NICE] = ColorPair(Cyan,White);
CRT_colors[CPU_NICE_TEXT] = ColorPair(Cyan,White);
CRT_colors[CPU_NORMAL] = ColorPair(Green,White);
CRT_colors[CPU_KERNEL] = ColorPair(Red,White);
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, White);
CRT_colors[CPU_IRQ] = ColorPair(Blue,White); CRT_colors[CPU_IRQ] = ColorPair(Blue,White);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,White); CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,White);
CRT_colors[CPU_STEAL] = ColorPair(Cyan,White);
CRT_colors[CPU_GUEST] = ColorPair(Cyan,White);
} else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE2) { } else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE2) {
CRT_colors[RESET_COLOR] = ColorPair(Black,Black); CRT_colors[RESET_COLOR] = ColorPair(Black,Black);
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,Black); CRT_colors[DEFAULT_COLOR] = ColorPair(Black,Black);
@ -390,7 +330,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,Black); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,Black);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Yellow,Black); CRT_colors[UPTIME] = ColorPair(Yellow,Black);
CRT_colors[BATTERY] = ColorPair(Yellow,Black);
CRT_colors[LARGE_NUMBER] = ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Blue,Black); CRT_colors[METER_TEXT] = ColorPair(Blue,Black);
CRT_colors[METER_VALUE] = ColorPair(Black,Black); CRT_colors[METER_VALUE] = ColorPair(Black,Black);
@ -421,27 +360,22 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = ColorPair(Yellow,Black); CRT_colors[GRAPH_9] = ColorPair(Yellow,Black);
CRT_colors[MEMORY_USED] = ColorPair(Green,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black);
CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black); CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black);
CRT_colors[MEMORY_BUFFERS_TEXT] = ColorPair(Cyan,Black);
CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black);
CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black);
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black);
CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,Black);
CRT_colors[LOAD] = ColorPair(White,Black); CRT_colors[LOAD] = ColorPair(White,Black);
CRT_colors[HELP_BOLD] = ColorPair(Blue,Black); CRT_colors[HELP_BOLD] = ColorPair(Blue,Black);
CRT_colors[CPU_NICE] = ColorPair(Cyan,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CLOCK] = ColorPair(White,Black); CRT_colors[CLOCK] = ColorPair(White,Black);
CRT_colors[CHECK_BOX] = ColorPair(Blue,Black); CRT_colors[CHECK_BOX] = ColorPair(Blue,Black);
CRT_colors[CHECK_MARK] = ColorPair(Black,Black); CRT_colors[CHECK_MARK] = ColorPair(Black,Black);
CRT_colors[CHECK_TEXT] = ColorPair(Black,Black); CRT_colors[CHECK_TEXT] = ColorPair(Black,Black);
CRT_colors[HOSTNAME] = ColorPair(White,Black);
CRT_colors[CPU_NICE] = ColorPair(Cyan,Black);
CRT_colors[CPU_NICE_TEXT] = ColorPair(Cyan,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black); CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black);
CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black); CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,Black); CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,Black);
CRT_colors[CPU_STEAL] = ColorPair(Black,Black);
CRT_colors[CPU_GUEST] = ColorPair(Black,Black);
} else if (CRT_colorScheme == COLORSCHEME_MIDNIGHT) { } else if (CRT_colorScheme == COLORSCHEME_MIDNIGHT) {
CRT_colors[RESET_COLOR] = ColorPair(White,Blue); CRT_colors[RESET_COLOR] = ColorPair(White,Blue);
CRT_colors[DEFAULT_COLOR] = ColorPair(White,Blue); CRT_colors[DEFAULT_COLOR] = ColorPair(White,Blue);
@ -453,7 +387,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[UPTIME] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[BATTERY] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Blue); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Blue);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Blue); CRT_colors[METER_TEXT] = ColorPair(Cyan,Blue);
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Blue); CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Blue);
@ -484,27 +417,22 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue); CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue);
CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue); CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue); CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue);
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue); CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue);
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White,Blue); CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White,Blue);
CRT_colors[LOAD] = A_BOLD | ColorPair(White,Blue); CRT_colors[LOAD] = A_BOLD | ColorPair(White,Blue);
CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Blue); CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[CPU_NORMAL] = A_BOLD | ColorPair(Green,Blue);
CRT_colors[CPU_KERNEL] = A_BOLD | ColorPair(Red,Blue);
CRT_colors[CLOCK] = ColorPair(White,Blue); CRT_colors[CLOCK] = ColorPair(White,Blue);
CRT_colors[CHECK_BOX] = ColorPair(Cyan,Blue); CRT_colors[CHECK_BOX] = ColorPair(Cyan,Blue);
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(White,Blue); CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(White,Blue);
CRT_colors[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue); CRT_colors[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue);
CRT_colors[HOSTNAME] = ColorPair(White,Blue); CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,Blue);
CRT_colors[CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan,Blue);
CRT_colors[CPU_NORMAL] = A_BOLD | ColorPair(Green,Blue);
CRT_colors[CPU_KERNEL] = A_BOLD | ColorPair(Red,Blue);
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Blue,Blue);
CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Black,Blue); CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Black,Blue);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Black,Blue); CRT_colors[CPU_SOFTIRQ] = ColorPair(Black,Blue);
CRT_colors[CPU_STEAL] = ColorPair(White,Blue);
CRT_colors[CPU_GUEST] = ColorPair(White,Blue);
} else if (CRT_colorScheme == COLORSCHEME_BLACKNIGHT) { } else if (CRT_colorScheme == COLORSCHEME_BLACKNIGHT) {
CRT_colors[RESET_COLOR] = ColorPair(Cyan,Black); CRT_colors[RESET_COLOR] = ColorPair(Cyan,Black);
CRT_colors[DEFAULT_COLOR] = ColorPair(Cyan,Black); CRT_colors[DEFAULT_COLOR] = ColorPair(Cyan,Black);
@ -516,7 +444,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Green,Black); CRT_colors[UPTIME] = ColorPair(Green,Black);
CRT_colors[BATTERY] = ColorPair(Green,Black);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Black); CRT_colors[METER_TEXT] = ColorPair(Cyan,Black);
CRT_colors[METER_VALUE] = ColorPair(Green,Black); CRT_colors[METER_VALUE] = ColorPair(Green,Black);
@ -547,27 +474,22 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black);
CRT_colors[MEMORY_USED] = ColorPair(Green,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black);
CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black);
CRT_colors[MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black);
CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black);
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black);
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green,Black); CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green,Black);
CRT_colors[LOAD] = A_BOLD; CRT_colors[LOAD] = A_BOLD;
CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CLOCK] = ColorPair(Green,Black); CRT_colors[CLOCK] = ColorPair(Green,Black);
CRT_colors[CHECK_BOX] = ColorPair(Green,Black); CRT_colors[CHECK_BOX] = ColorPair(Green,Black);
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,Black); CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,Black);
CRT_colors[CHECK_TEXT] = ColorPair(Cyan,Black); CRT_colors[CHECK_TEXT] = ColorPair(Cyan,Black);
CRT_colors[HOSTNAME] = ColorPair(Green,Black);
CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,Black); CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,Black);
CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black); CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,Black); CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,Black);
CRT_colors[CPU_STEAL] = ColorPair(Cyan,Black);
CRT_colors[CPU_GUEST] = ColorPair(Cyan,Black);
} else { } else {
/* Default */ /* Default */
CRT_colors[RESET_COLOR] = ColorPair(White,Black); CRT_colors[RESET_COLOR] = ColorPair(White,Black);
@ -580,7 +502,6 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[UPTIME] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[BATTERY] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Black); CRT_colors[METER_TEXT] = ColorPair(Cyan,Black);
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Black);
@ -611,26 +532,21 @@ void CRT_setColors(int colorScheme) {
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black);
CRT_colors[MEMORY_USED] = ColorPair(Green,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black);
CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black);
CRT_colors[MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black);
CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black);
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL;
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD; CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD;
CRT_colors[LOAD] = A_BOLD; CRT_colors[LOAD] = A_BOLD;
CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CLOCK] = A_BOLD; CRT_colors[CLOCK] = A_BOLD;
CRT_colors[CHECK_BOX] = ColorPair(Cyan,Black); CRT_colors[CHECK_BOX] = ColorPair(Cyan,Black);
CRT_colors[CHECK_MARK] = A_BOLD; CRT_colors[CHECK_MARK] = A_BOLD;
CRT_colors[CHECK_TEXT] = A_NORMAL; CRT_colors[CHECK_TEXT] = A_NORMAL;
CRT_colors[HOSTNAME] = A_BOLD;
CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black); CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black);
CRT_colors[CPU_IRQ] = ColorPair(Yellow,Black); CRT_colors[CPU_IRQ] = ColorPair(Yellow,Black);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Magenta,Black); CRT_colors[CPU_SOFTIRQ] = ColorPair(Magenta,Black);
CRT_colors[CPU_STEAL] = ColorPair(Cyan,Black);
CRT_colors[CPU_GUEST] = ColorPair(Cyan,Black);
} }
} }

40
CRT.h
View File

@ -4,13 +4,21 @@
#define HEADER_CRT #define HEADER_CRT
/* /*
htop - CRT.h htop - CRT.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifdef HAVE_EXECINFO_H
#endif #include <curses.h>
#include <signal.h>
#include <stdlib.h>
#include <stdbool.h>
#include "String.h"
#include "config.h"
#include "debug.h"
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j) #define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
@ -32,7 +40,8 @@ in the source distribution for its full text.
//#link curses //#link curses
#include <stdbool.h> bool CRT_hasColors;
typedef enum ColorElements_ { typedef enum ColorElements_ {
RESET_COLOR, RESET_COLOR,
@ -49,7 +58,7 @@ typedef enum ColorElements_ {
METER_VALUE, METER_VALUE,
LED_COLOR, LED_COLOR,
UPTIME, UPTIME,
BATTERY, TASKS_TOTAL,
TASKS_RUNNING, TASKS_RUNNING,
SWAP, SWAP,
PROCESS, PROCESS,
@ -76,7 +85,6 @@ typedef enum ColorElements_ {
GRAPH_9, GRAPH_9,
MEMORY_USED, MEMORY_USED,
MEMORY_BUFFERS, MEMORY_BUFFERS,
MEMORY_BUFFERS_TEXT,
MEMORY_CACHE, MEMORY_CACHE,
LOAD, LOAD,
LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIFTEEN,
@ -86,47 +94,33 @@ typedef enum ColorElements_ {
CHECK_MARK, CHECK_MARK,
CHECK_TEXT, CHECK_TEXT,
CLOCK, CLOCK,
HELP_BOLD,
HOSTNAME,
CPU_NICE, CPU_NICE,
CPU_NICE_TEXT,
CPU_NORMAL, CPU_NORMAL,
CPU_KERNEL, CPU_KERNEL,
HELP_BOLD,
CPU_IOWAIT, CPU_IOWAIT,
CPU_IRQ, CPU_IRQ,
CPU_SOFTIRQ, CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
void CRT_fatalError(const char* note) __attribute__ ((noreturn));
// TODO: centralize these in Settings. // TODO: centralize these in Settings.
extern int CRT_colorScheme; extern int CRT_delay;
extern bool CRT_utf8; extern int CRT_colorScheme;
extern int CRT_colors[LAST_COLORELEMENT]; extern int CRT_colors[LAST_COLORELEMENT];
extern int CRT_cursorX;
extern int CRT_scrollHAmount;
char* CRT_termType; char* CRT_termType;
void *backtraceArray[128];
// TODO: pass an instance of Settings instead. // TODO: pass an instance of Settings instead.
void CRT_init(int delay, int colorScheme); void CRT_init(int delay, int colorScheme);
void CRT_done(); void CRT_done();
void CRT_fatalError(const char* note);
int CRT_readKey(); int CRT_readKey();
void CRT_disableDelay(); void CRT_disableDelay();

View File

@ -1,12 +1,5 @@
/*
htop - CategoriesPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "CategoriesPanel.h" #include "CategoriesPanel.h"
#include "AvailableMetersPanel.h" #include "AvailableMetersPanel.h"
#include "MetersPanel.h" #include "MetersPanel.h"
#include "DisplayOptionsPanel.h" #include "DisplayOptionsPanel.h"
@ -14,13 +7,12 @@ in the source distribution for its full text.
#include "ColorsPanel.h" #include "ColorsPanel.h"
#include "AvailableColumnsPanel.h" #include "AvailableColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
/*{ /*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct CategoriesPanel_ { typedef struct CategoriesPanel_ {
Panel super; Panel super;
@ -31,17 +23,17 @@ typedef struct CategoriesPanel_ {
}*/ }*/
static const char* MetersFunctions[] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; static char* MetersFunctions[10] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
static const char* AvailableMetersFunctions[] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done ", NULL}; static char* AvailableMetersFunctions[10] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done "};
static const char* DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; static char* DisplayOptionsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
static const char* ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; static char* ColumnsFunctions[10] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
static const char* ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; static char* ColorsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
static const char* AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL}; static char* AvailableColumnsFunctions[10] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done "};
static void CategoriesPanel_delete(Object* object) { static void CategoriesPanel_delete(Object* object) {
Panel* super = (Panel*) object; Panel* super = (Panel*) object;
@ -54,26 +46,26 @@ void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
Panel* leftMeters = (Panel*) MetersPanel_new(this->settings, "Left column", this->settings->header->leftMeters, this->scr); Panel* leftMeters = (Panel*) MetersPanel_new(this->settings, "Left column", this->settings->header->leftMeters, this->scr);
Panel* rightMeters = (Panel*) MetersPanel_new(this->settings, "Right column", this->settings->header->rightMeters, this->scr); Panel* rightMeters = (Panel*) MetersPanel_new(this->settings, "Right column", this->settings->header->rightMeters, this->scr);
Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, leftMeters, rightMeters, this->scr); Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, leftMeters, rightMeters, this->scr);
ScreenManager_add(this->scr, leftMeters, FunctionBar_new(MetersFunctions, NULL, NULL), 20); ScreenManager_add(this->scr, leftMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, rightMeters, FunctionBar_new(MetersFunctions, NULL, NULL), 20); ScreenManager_add(this->scr, rightMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, availableMeters, FunctionBar_new(AvailableMetersFunctions, NULL, NULL), -1); ScreenManager_add(this->scr, availableMeters, FunctionBar_new(10, AvailableMetersFunctions, NULL, NULL), -1);
} }
static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) { static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) {
Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr); Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, displayOptions, FunctionBar_new(DisplayOptionsFunctions, NULL, NULL), -1); ScreenManager_add(this->scr, displayOptions, FunctionBar_new(10, DisplayOptionsFunctions, NULL, NULL), -1);
} }
static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) { static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr); Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, colors, FunctionBar_new(ColorsFunctions, NULL, NULL), -1); ScreenManager_add(this->scr, colors, FunctionBar_new(10, ColorsFunctions, NULL, NULL), -1);
} }
static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) { static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
Panel* columns = (Panel*) ColumnsPanel_new(this->settings, this->scr); Panel* columns = (Panel*) ColumnsPanel_new(this->settings, this->scr);
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(this->settings, columns, this->scr); Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(this->settings, columns, this->scr);
ScreenManager_add(this->scr, columns, FunctionBar_new(ColumnsFunctions, NULL, NULL), 20); ScreenManager_add(this->scr, columns, FunctionBar_new(10, ColumnsFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, availableColumns, FunctionBar_new(AvailableColumnsFunctions, NULL, NULL), -1); ScreenManager_add(this->scr, availableColumns, FunctionBar_new(10, AvailableColumnsFunctions, NULL, NULL), -1);
} }
static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) { static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
@ -87,9 +79,7 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
result = HANDLED; result = HANDLED;
break; break;
case KEY_UP: case KEY_UP:
case KEY_CTRLP:
case KEY_DOWN: case KEY_DOWN:
case KEY_CTRLN:
case KEY_NPAGE: case KEY_NPAGE:
case KEY_PPAGE: case KEY_PPAGE:
case KEY_HOME: case KEY_HOME:
@ -101,12 +91,6 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
result = HANDLED; result = HANDLED;
break; break;
} }
default:
if (isalpha(ch))
result = Panel_selectByTyping(super, ch);
if (result == BREAK_LOOP)
result = IGNORED;
break;
} }
if (result == HANDLED) { if (result == HANDLED) {
@ -132,21 +116,15 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
return result; return result;
} }
PanelClass CategoriesPanel_class = {
.super = {
.extends = Class(Panel),
.delete = CategoriesPanel_delete
},
.eventHandler = CategoriesPanel_eventHandler
};
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr) { CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr) {
CategoriesPanel* this = AllocThis(CategoriesPanel); CategoriesPanel* this = (CategoriesPanel*) malloc(sizeof(CategoriesPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true); Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = CategoriesPanel_delete;
this->settings = settings; this->settings = settings;
this->scr = scr; this->scr = scr;
super->eventHandler = CategoriesPanel_eventHandler;
Panel_setHeader(super, "Setup"); Panel_setHeader(super, "Setup");
Panel_add(super, (Object*) ListItem_new("Meters", 0)); Panel_add(super, (Object*) ListItem_new("Meters", 0));
Panel_add(super, (Object*) ListItem_new("Display options", 0)); Panel_add(super, (Object*) ListItem_new("Display options", 0));

View File

@ -2,16 +2,19 @@
#ifndef HEADER_CategoriesPanel #ifndef HEADER_CategoriesPanel
#define HEADER_CategoriesPanel #define HEADER_CategoriesPanel
/*
htop - CategoriesPanel.h #include "AvailableMetersPanel.h"
(C) 2004-2011 Hisham H. Muhammad #include "MetersPanel.h"
Released under the GNU GPL, see the COPYING file #include "DisplayOptionsPanel.h"
in the source distribution for its full text. #include "ColumnsPanel.h"
*/ #include "ColorsPanel.h"
#include "AvailableColumnsPanel.h"
#include "Panel.h" #include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h" #include "debug.h"
#include <assert.h>
typedef struct CategoriesPanel_ { typedef struct CategoriesPanel_ {
Panel super; Panel super;
@ -23,8 +26,6 @@ typedef struct CategoriesPanel_ {
void CategoriesPanel_makeMetersPage(CategoriesPanel* this); void CategoriesPanel_makeMetersPage(CategoriesPanel* this);
extern PanelClass CategoriesPanel_class;
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr); CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr);
#endif #endif

132
ChangeLog
View File

@ -1,136 +1,4 @@
What's new in version 1.0.3
* Tag all children ('c' key)
* Fixes in accounting of guest time when using virtualization
(thanks to Patrick Marlier)
* Performance improvements
(thanks to Jann Horn)
* Further performance improvements due to conditional parsing
of IO data depending on selected fields.
* Better consistency in coloring.
* Increase limit of buffer when tracing a deep nested process tree.
* Display pagefault stats.
* BUGFIX: Fix crash when adding meters and toggling detailed CPU time.
(thanks to Dawid Gajownik)
* Add column to track the OOM-killer score of processes
(thanks to Leigh Simpson)
What's new in version 1.0.2
* Add IO priority support ('i' key)
* Avoid deleting .htoprc if it is a symlink
* Fail gracefully when /proc is not mounted
(thanks to Philipp Hagemeister)
* Option to update process names on every refresh
(thanks to Rob Hoelz)
* BUGFIX: Fix crashes when process list is empty
What's new in version 1.0.1
* Move .htoprc to XDG-compliant path ~/.config/htop/htoprc,
respecting $XDG_CONFIG_HOME
(thanks to Hadzhimurad Ustarkhan for the suggestion.)
* Safer behavior on the kill screen, to make it harder to kill the wrong process.
* Fix for building in FreeBSD 8.2
(thanks to Trond Endrestol)
* BUGFIX: behavior of 'F' (follow) key was broken, also affecting the
persistence of mouse selections.
* BUGFIX: keep main panel up-to-date when running the screen manager,
to fix crash when processes die while on the F9/Kill screen.
What's new in version 1.0
* Performance improvements
* Support for splitting CPU meters into two or four columns
(thanks to Wim Heirman)
* Switch from PLPA, which is now deprecated, to HWLOC.
* Bring back support for native Linux sched_setaffinity,
so we don't have to use HWLOC where we don't need to.
* Support for typing in user names and column fields in selection panels.
* 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.)
* Stricter checks for command-line options
(thanks to Sebastian Pipping)
* Incremental filtering
(thanks to Seth Heeren for the idea and initial implementation)
* Try harder to find the ncurses header
(thanks to Moritz Barsnick)
* Man page updates
(thanks to Vincent Launchbury)
* BUGFIX: Support larger numbers for process times.
(thanks to Tristan Nakagawa for the report.)
* BUGFIX: Segfault in BarMeterMode_draw() for small terminal widths
(patch by Sebastian Pipping)
What's new in version 0.9
* Add support for "steal"/guest CPU time measurement
in virtualization environments
* Expand and collapse subtrees using '+' and '-' when in tree-view
* Support for cgroups
(thanks to Guillaume Zitta and Daniel Lezcano)
* Show custom thread names
(thanks to Anders Torger)
* Add support for STARTTIME field
* Upgrade PLPA to version 1.3.2
* Fix license terms with regard to PLPA
(thanks to Tom Callaway)
* getopt-based long options and --no-color
(thanks to Vincent Launchbury)
* BUGFIX: Fix display of nan% in CPU meters
(thanks to Steven Hampson)
* BUGFIX: Fix memory leak
(thanks to Pavol Rusnak)
* Add Bash/emacs style navigation keys
(thanks to Daniel Schuler)
* Improve battery meter support
(thanks to Richard W.)
* BUGFIX: Fix IO-wait color in "Black on White" scheme
* BUGFIX: Fix search by process name when list is filtered by user.
(thanks to Sergej Pupykin for the report.)
* BUGFIX: Fix alignment for display of memory values above 100G (sign of the times!)
(thanks to Jan van Haarst for the report.)
What's new in version 0.8.3
* BUGFIX: Fix crash on F6 key
(thanks to Rainer Suhm)
* BUGFIX: Fix a minor bug which affected the build process.
What's new in version 0.8.2
* Integrated lsof (press 'l')
* Fix display of gigabyte-sized values
(thanks to Andika Triwidada)
* Option to display hostname in the meters area
* Rename VEID to CTID in OpenVZ systems
(thanks to Thorsten Schifferdecker)
* Corrections to the desktop entry file
(thanks by Samuli Suominen)
* BUGFIX: Correct page size calculation for FreeBSD systems
(thanks to Andrew Paulsen)
* Allow compilation without PLPA on systems that don't support it
(thanks to Timothy Redaelli)
* BUGFIX: Fix missing tree view when userland threads are hidden
(thanks to Josh Stone)
* BUGFIX: Fix for VPID on OpenVZ systems
(thanks to Wolfgang Frisch)
What's new in version 0.8.1
* Linux-VServer support
(thanks to Jonathan Sambrook and Benedikt Bohm)
* Battery meter
(thanks to Ian Page Hands)
* BUGFIX: Fix collection of IO stats in multithreaded processes
(thanks to Gerhard Heift)
* Remove assertion that fails on hardened kernels
(thanks to Wolfram Schlich for the report)
What's new in version 0.8 What's new in version 0.8
* Ability to change sort column with the mouse by * Ability to change sort column with the mouse by

View File

@ -1,29 +1,33 @@
/* /*
htop - CheckItem.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "CheckItem.h" #include "CheckItem.h"
#include "Object.h"
#include "CRT.h" #include "CRT.h"
#include <assert.h> #include "debug.h"
#include <stdlib.h>
/*{ /*{
#include "Object.h"
typedef struct CheckItem_ { typedef struct CheckItem_ {
Object super; Object super;
char* text; char* text;
bool* ref;
bool value; bool value;
bool* ref;
} CheckItem; } CheckItem;
}*/ }*/
#ifdef DEBUG
char* CHECKITEM_CLASS = "CheckItem";
#else
#define CHECKITEM_CLASS NULL
#endif
static void CheckItem_delete(Object* cast) { static void CheckItem_delete(Object* cast) {
CheckItem* this = (CheckItem*)cast; CheckItem* this = (CheckItem*)cast;
assert (this != NULL); assert (this != NULL);
@ -44,13 +48,11 @@ static void CheckItem_display(Object* cast, RichString* out) {
RichString_append(out, CRT_colors[CHECK_TEXT], this->text); RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
} }
ObjectClass CheckItem_class = {
.display = CheckItem_display,
.delete = CheckItem_delete
};
CheckItem* CheckItem_new(char* text, bool* ref, bool value) { CheckItem* CheckItem_new(char* text, bool* ref, bool value) {
CheckItem* this = AllocThis(CheckItem); CheckItem* this = malloc(sizeof(CheckItem));
Object_setClass(this, CHECKITEM_CLASS);
((Object*)this)->display = CheckItem_display;
((Object*)this)->delete = CheckItem_delete;
this->text = text; this->text = text;
this->value = value; this->value = value;
this->ref = ref; this->ref = ref;

View File

@ -3,23 +3,31 @@
#ifndef HEADER_CheckItem #ifndef HEADER_CheckItem
#define HEADER_CheckItem #define HEADER_CheckItem
/* /*
htop - CheckItem.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h" #include "Object.h"
#include "CRT.h"
#include "debug.h"
typedef struct CheckItem_ { typedef struct CheckItem_ {
Object super; Object super;
char* text; char* text;
bool* ref;
bool value; bool value;
bool* ref;
} CheckItem; } CheckItem;
extern ObjectClass CheckItem_class; #ifdef DEBUG
extern char* CHECKITEM_CLASS;
#else
#define CHECKITEM_CLASS NULL
#endif
CheckItem* CheckItem_new(char* text, bool* ref, bool value); CheckItem* CheckItem_new(char* text, bool* ref, bool value);

View File

@ -1,19 +1,16 @@
/* /*
htop - ClockMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ClockMeter.h" #include "ClockMeter.h"
#include "Meter.h"
#include "CRT.h"
#include <time.h> #include <time.h>
/*{ #include "debug.h"
#include "Meter.h"
}*/
int ClockMeter_attributes[] = { int ClockMeter_attributes[] = {
CLOCK CLOCK
@ -21,20 +18,17 @@ int ClockMeter_attributes[] = {
static void ClockMeter_setValues(Meter* this, char* buffer, int size) { static void ClockMeter_setValues(Meter* this, char* buffer, int size) {
time_t t = time(NULL); time_t t = time(NULL);
struct tm result; struct tm *lt = localtime(&t);
struct tm *lt = localtime_r(&t, &result);
this->values[0] = lt->tm_hour * 60 + lt->tm_min; this->values[0] = lt->tm_hour * 60 + lt->tm_min;
strftime(buffer, size, "%H:%M:%S", lt); strftime(buffer, size, "%H:%M:%S", lt);
} }
MeterClass ClockMeter_class = { MeterType ClockMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.setValues = ClockMeter_setValues, .setValues = ClockMeter_setValues,
.defaultMode = TEXT_METERMODE, .display = NULL,
.mode = TEXT_METERMODE,
.total = 100.0, .total = 100.0,
.items = 1,
.attributes = ClockMeter_attributes, .attributes = ClockMeter_attributes,
.name = "Clock", .name = "Clock",
.uiName = "Clock", .uiName = "Clock",

View File

@ -3,16 +3,20 @@
#ifndef HEADER_ClockMeter #ifndef HEADER_ClockMeter
#define HEADER_ClockMeter #define HEADER_ClockMeter
/* /*
htop - ClockMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include <time.h>
#include "debug.h"
extern int ClockMeter_attributes[]; extern int ClockMeter_attributes[];
extern MeterClass ClockMeter_class; extern MeterType ClockMeter;
#endif #endif

View File

@ -1,18 +1,14 @@
/*
htop - ColorsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "ColorsPanel.h"
#include "CRT.h" #include "CRT.h"
#include "CheckItem.h" #include "ColorsPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <string.h>
// TO ADD A NEW SCHEME: // TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h // * Increment the size of bool check in ColorsPanel.h
@ -21,9 +17,6 @@ in the source distribution for its full text.
// * Add the colors in CRT_setColors // * Add the colors in CRT_setColors
/*{ /*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct ColorsPanel_ { typedef struct ColorsPanel_ {
Panel super; Panel super;
@ -34,7 +27,7 @@ typedef struct ColorsPanel_ {
}*/ }*/
static const char* ColorSchemes[] = { static char* ColorSchemes[] = {
"Default", "Default",
"Monochromatic", "Monochromatic",
"Black on White", "Black on White",
@ -51,7 +44,7 @@ static void ColorsPanel_delete(Object* object) {
free(this); free(this);
} }
static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) { static HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
ColorsPanel* this = (ColorsPanel*) super; ColorsPanel* this = (ColorsPanel*) super;
HandlerResult result = IGNORED; HandlerResult result = IGNORED;
@ -74,7 +67,7 @@ static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) {
this->settings->changed = true; this->settings->changed = true;
Header* header = this->settings->header; Header* header = this->settings->header;
CRT_setColors(mark); CRT_setColors(mark);
Panel* menu = (Panel*) Vector_get(this->scr->panels, 0); Panel* menu = (Panel*) Vector_get(this->scr->items, 0);
Header_draw(header); Header_draw(header);
RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]); RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]);
RichString_setAttr(&(menu->header), CRT_colors[PANEL_HEADER_UNFOCUS]); RichString_setAttr(&(menu->header), CRT_colors[PANEL_HEADER_UNFOCUS]);
@ -83,25 +76,19 @@ static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) {
return result; return result;
} }
PanelClass ColorsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = ColorsPanel_delete
},
.eventHandler = ColorsPanel_eventHandler
};
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) { ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) {
ColorsPanel* this = AllocThis(ColorsPanel); ColorsPanel* this = (ColorsPanel*) malloc(sizeof(ColorsPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true); Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = ColorsPanel_delete;
this->settings = settings; this->settings = settings;
this->scr = scr; this->scr = scr;
super->eventHandler = ColorsPanel_EventHandler;
Panel_setHeader(super, "Colors"); Panel_setHeader(super, "Colors");
for (int i = 0; ColorSchemes[i] != NULL; i++) { for (int i = 0; ColorSchemes[i] != NULL; i++) {
Panel_add(super, (Object*) CheckItem_new(strdup(ColorSchemes[i]), NULL, false)); Panel_add(super, (Object*) CheckItem_new(String_copy(ColorSchemes[i]), NULL, false));
} }
CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true); CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true);
return this; return this;

View File

@ -2,12 +2,16 @@
#ifndef HEADER_ColorsPanel #ifndef HEADER_ColorsPanel
#define HEADER_ColorsPanel #define HEADER_ColorsPanel
/*
htop - ColorsPanel.h #include "CRT.h"
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file #include "Panel.h"
in the source distribution for its full text. #include "CheckItem.h"
*/ #include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
// TO ADD A NEW SCHEME: // TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h // * Increment the size of bool check in ColorsPanel.h
@ -15,9 +19,6 @@ in the source distribution for its full text.
// * Add a define in CRT.h that matches the order of the array // * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors // * Add the colors in CRT_setColors
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct ColorsPanel_ { typedef struct ColorsPanel_ {
Panel super; Panel super;
@ -27,8 +28,6 @@ typedef struct ColorsPanel_ {
} ColorsPanel; } ColorsPanel;
extern PanelClass ColorsPanel_class;
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr); ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr);
#endif #endif

View File

@ -1,23 +1,15 @@
/*
htop - ColumnsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "ColumnsPanel.h" #include "ColumnsPanel.h"
#include "String.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
/*{
#include "Panel.h" #include "Panel.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct ColumnsPanel_ { typedef struct ColumnsPanel_ {
Panel super; Panel super;
@ -38,7 +30,7 @@ static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
int selected = Panel_getSelectedIndex(super); int selected = Panel_getSelectedIndex(super);
HandlerResult result = IGNORED; HandlerResult result = IGNORED;
int size = Panel_size(super); int size = Panel_getSize(super);
switch(ch) { switch(ch) {
case KEY_F(7): case KEY_F(7):
@ -68,35 +60,21 @@ static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
result = HANDLED; result = HANDLED;
break; break;
} }
default:
{
if (isalpha(ch))
result = Panel_selectByTyping(super, ch);
if (result == BREAK_LOOP)
result = IGNORED;
break;
}
} }
if (result == HANDLED) if (result == HANDLED)
ColumnsPanel_update(super); ColumnsPanel_update(super);
return result; return result;
} }
PanelClass ColumnsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = ColumnsPanel_delete
},
.eventHandler = ColumnsPanel_eventHandler
};
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr) { ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr) {
ColumnsPanel* this = AllocThis(ColumnsPanel); ColumnsPanel* this = (ColumnsPanel*) malloc(sizeof(ColumnsPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true); Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = ColumnsPanel_delete;
this->settings = settings; this->settings = settings;
this->scr = scr; this->scr = scr;
super->eventHandler = ColumnsPanel_eventHandler;
Panel_setHeader(super, "Active Columns"); Panel_setHeader(super, "Active Columns");
ProcessField* fields = this->settings->pl->fields; ProcessField* fields = this->settings->pl->fields;
@ -117,19 +95,16 @@ int ColumnsPanel_fieldNameToIndex(const char* name) {
void ColumnsPanel_update(Panel* super) { void ColumnsPanel_update(Panel* super) {
ColumnsPanel* this = (ColumnsPanel*) super; ColumnsPanel* this = (ColumnsPanel*) super;
int size = Panel_size(super); int size = Panel_getSize(super);
this->settings->changed = true; this->settings->changed = true;
// FIXME: this is crappily inefficient // FIXME: this is crappily inefficient
free(this->settings->pl->fields); free(this->settings->pl->fields);
this->settings->pl->fields = (ProcessField*) malloc(sizeof(ProcessField) * (size+1)); this->settings->pl->fields = (ProcessField*) malloc(sizeof(ProcessField) * (size+1));
this->settings->pl->flags = 0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
char* text = ((ListItem*) Panel_get(super, i))->value; char* text = ((ListItem*) Panel_get(super, i))->value;
int j = ColumnsPanel_fieldNameToIndex(text); int j = ColumnsPanel_fieldNameToIndex(text);
if (j > 0) { if (j > 0)
this->settings->pl->fields[i] = j; this->settings->pl->fields[i] = j;
this->settings->pl->flags |= Process_fieldFlags[j];
}
} }
this->settings->pl->fields[size] = 0; this->settings->pl->fields[size] = 0;
} }

View File

@ -2,17 +2,16 @@
#ifndef HEADER_ColumnsPanel #ifndef HEADER_ColumnsPanel
#define HEADER_ColumnsPanel #define HEADER_ColumnsPanel
/*
htop - ColumnsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h" #include "Panel.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct ColumnsPanel_ { typedef struct ColumnsPanel_ {
Panel super; Panel super;
@ -21,8 +20,6 @@ typedef struct ColumnsPanel_ {
} ColumnsPanel; } ColumnsPanel;
extern PanelClass ColumnsPanel_class;
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr); ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr);
int ColumnsPanel_fieldNameToIndex(const char* name); int ColumnsPanel_fieldNameToIndex(const char* name);

227
DebugMemory.c Normal file
View File

@ -0,0 +1,227 @@
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#undef strdup
#undef malloc
#undef realloc
#undef calloc
#undef free
#include "DebugMemory.h"
/*{
typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ {
int magic;
void* data;
char* file;
int line;
DebugMemoryItem* next;
};
typedef struct DebugMemory_ {
DebugMemoryItem* first;
int allocations;
int deallocations;
int size;
bool totals;
FILE* file;
} DebugMemory;
}*/
#if defined(DEBUG)
static DebugMemory* singleton = NULL;
void DebugMemory_new() {
if (singleton)
return;
singleton = malloc(sizeof(DebugMemory));
singleton->first = NULL;
singleton->allocations = 0;
singleton->deallocations = 0;
singleton->size = 0;
#ifdef DEBUG_ALLOC
singleton->file = fopen("/tmp/htop-debug-alloc.txt", "w");
#else
singleton->file = NULL;
#endif
singleton->totals = true;
//singleton->file = NULL;
}
void* DebugMemory_malloc(int size, char* file, int line, char* str) {
void* data = malloc(size);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
}
return data;
}
void* DebugMemory_calloc(int a, int b, char* file, int line) {
void* data = calloc(a, b);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d\n", a*b, file, line);
}
return data;
}
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str) {
if (ptr != NULL)
DebugMemory_registerDeallocation(ptr, file, line);
void* data = realloc(ptr, size);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
}
return data;
}
void* DebugMemory_strdup(char* str, char* file, int line) {
assert(str);
char* data = strdup(str);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d\n", (int) strlen(str), file, line);
}
return data;
}
void DebugMemory_free(void* data, char* file, int line) {
assert(data);
DebugMemory_registerDeallocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "free\t%s:%d\n", file, line);
}
free(data);
}
void DebugMemory_assertSize() {
if (!singleton->first) {
assert (singleton->size == 0);
}
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
walk = walk->next;
}
assert (i == singleton->size);
}
int DebugMemory_getBlockCount() {
if (!singleton->first) {
return 0;
}
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
walk = walk->next;
}
return i;
}
void DebugMemory_registerAllocation(void* data, char* file, int line) {
if (!singleton)
DebugMemory_new();
DebugMemory_assertSize();
DebugMemoryItem* item = (DebugMemoryItem*) malloc(sizeof(DebugMemoryItem));
item->magic = 11061980;
item->data = data;
item->file = file;
item->line = line;
item->next = NULL;
int val = DebugMemory_getBlockCount();
if (singleton->first == NULL) {
assert (val == 0);
singleton->first = item;
} else {
DebugMemoryItem* walk = singleton->first;
while (true) {
if (walk->next == NULL) {
walk->next = item;
break;
}
assert(walk->magic == 11061980);
walk = walk->next;
}
}
int nval = DebugMemory_getBlockCount();
assert(nval == val + 1);
singleton->allocations++;
singleton->size++;
DebugMemory_assertSize();
}
void DebugMemory_registerDeallocation(void* data, char* file, int line) {
assert(singleton);
assert(singleton->first);
DebugMemoryItem* walk = singleton->first;
DebugMemoryItem* prev = NULL;
int val = DebugMemory_getBlockCount();
while (walk != NULL) {
assert(walk->magic == 11061980);
if (walk->data == data) {
if (prev == NULL) {
singleton->first = walk->next;
} else {
prev->next = walk->next;
}
free(walk);
assert(DebugMemory_getBlockCount() == val - 1);
singleton->deallocations++;
singleton->size--;
DebugMemory_assertSize();
return;
}
DebugMemoryItem* tmp = walk;
walk = walk->next;
prev = tmp;
}
DebugMemory_report();
fprintf(stderr, "Couldn't find allocation for memory freed at %s:%d\n", file, line);
assert(false);
}
void DebugMemory_report() {
assert(singleton);
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line);
walk = walk->next;
}
fprintf(stderr, "Total:\n");
fprintf(stderr, "%d allocations\n", singleton->allocations);
fprintf(stderr, "%d deallocations\n", singleton->deallocations);
fprintf(stderr, "%d size\n", singleton->size);
fprintf(stderr, "%d non-freed blocks\n", i);
if (singleton->file)
fclose(singleton->file);
}
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif

71
DebugMemory.h Normal file
View File

@ -0,0 +1,71 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DebugMemory
#define HEADER_DebugMemory
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#undef strdup
#undef malloc
#undef realloc
#undef calloc
#undef free
typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ {
int magic;
void* data;
char* file;
int line;
DebugMemoryItem* next;
};
typedef struct DebugMemory_ {
DebugMemoryItem* first;
int allocations;
int deallocations;
int size;
bool totals;
FILE* file;
} DebugMemory;
#if defined(DEBUG)
void DebugMemory_new();
void* DebugMemory_malloc(int size, char* file, int line, char* str);
void* DebugMemory_calloc(int a, int b, char* file, int line);
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str);
void* DebugMemory_strdup(char* str, char* file, int line);
void DebugMemory_free(void* data, char* file, int line);
void DebugMemory_assertSize();
int DebugMemory_getBlockCount();
void DebugMemory_registerAllocation(void* data, char* file, int line);
void DebugMemory_registerDeallocation(void* data, char* file, int line);
void DebugMemory_report();
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif
#endif

View File

@ -1,23 +1,16 @@
/*
htop - DisplayOptionsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "DisplayOptionsPanel.h" #include "DisplayOptionsPanel.h"
#include "CheckItem.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
/*{
#include "Panel.h" #include "Panel.h"
#include "CheckItem.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct DisplayOptionsPanel_ { typedef struct DisplayOptionsPanel_ {
Panel super; Panel super;
@ -54,42 +47,31 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
this->settings->changed = true; this->settings->changed = true;
Header* header = this->settings->header; Header* header = this->settings->header;
Header_calculateHeight(header); Header_calculateHeight(header);
Header_reinit(header);
Header_draw(header); Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
} }
return result; return result;
} }
PanelClass DisplayOptionsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = DisplayOptionsPanel_delete
},
.eventHandler = DisplayOptionsPanel_eventHandler
};
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) { DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) {
DisplayOptionsPanel* this = AllocThis(DisplayOptionsPanel); DisplayOptionsPanel* this = (DisplayOptionsPanel*) malloc(sizeof(DisplayOptionsPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true); Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = DisplayOptionsPanel_delete;
this->settings = settings; this->settings = settings;
this->scr = scr; this->scr = scr;
super->eventHandler = DisplayOptionsPanel_eventHandler;
Panel_setHeader(super, "Display options"); Panel_setHeader(super, "Display options");
Panel_add(super, (Object*) CheckItem_new(strdup("Tree view"), &(settings->pl->treeView), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Tree view"), &(settings->pl->treeView), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Shadow other users' processes"), &(settings->pl->shadowOtherUsers), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Hide kernel threads"), &(settings->pl->hideKernelThreads), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Hide userland threads"), &(settings->pl->hideUserlandThreads), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Display threads in a different color"), &(settings->pl->highlightThreads), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Display threads in a different color"), &(settings->pl->highlightThreads), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Show custom thread names"), &(settings->pl->showThreadNames), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Highlight large numbers in memory counters"), &(settings->pl->highlightMegabytes), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Leave a margin around header"), &(settings->header->margin), false)); Panel_add(super, (Object*) CheckItem_new(String_copy("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ)"), &(settings->pl->detailedCPUTime), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)"), &(settings->pl->detailedCPUTime), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Count CPUs from 0 instead of 1"), &(settings->pl->countCPUsFromZero), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Update process names on every refresh"), &(settings->pl->updateProcessNames), false));
Panel_add(super, (Object*) CheckItem_new(strdup("Add guest time in CPU meter percentage"), &(settings->pl->accountGuestInCPUMeter), false));
return this; return this;
} }

View File

@ -2,17 +2,17 @@
#ifndef HEADER_DisplayOptionsPanel #ifndef HEADER_DisplayOptionsPanel
#define HEADER_DisplayOptionsPanel #define HEADER_DisplayOptionsPanel
/*
htop - DisplayOptionsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h" #include "Panel.h"
#include "CheckItem.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct DisplayOptionsPanel_ { typedef struct DisplayOptionsPanel_ {
Panel super; Panel super;
@ -21,8 +21,6 @@ typedef struct DisplayOptionsPanel_ {
} DisplayOptionsPanel; } DisplayOptionsPanel;
extern PanelClass DisplayOptionsPanel_class;
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr); DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr);
#endif #endif

View File

@ -1,21 +1,23 @@
/* /*
htop - FunctionBar.c htop - FunctionBar.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h"
#include "FunctionBar.h" #include "FunctionBar.h"
#include "CRT.h" #include "CRT.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <curses.h>
/*{ /*{
#include "Object.h"
typedef struct FunctionBar_ { typedef struct FunctionBar_ {
Object super; Object super;
@ -28,76 +30,74 @@ typedef struct FunctionBar_ {
}*/ }*/
static const char* FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL}; #ifdef DEBUG
char* FUNCTIONBAR_CLASS = "FunctionBar";
#else
#define FUNCTIONBAR_CLASS NULL
#endif
static const char* FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL}; static char* FunctionBar_FKeys[10] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"};
static int FunctionBar_FEvents[] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)}; static char* FunctionBar_FLabels[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
ObjectClass FunctionBar_class = { static int FunctionBar_FEvents[10] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)};
.delete = FunctionBar_delete
};
FunctionBar* FunctionBar_new(const char** functions, const char** keys, int* events) { FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) {
FunctionBar* this = AllocThis(FunctionBar); FunctionBar* this = malloc(sizeof(FunctionBar));
this->functions = calloc(16, sizeof(char*)); Object_setClass(this, FUNCTIONBAR_CLASS);
if (!functions) { ((Object*) this)->delete = FunctionBar_delete;
functions = FunctionBar_FLabels; this->functions = functions;
} this->size = size;
for (int i = 0; i < 15 && functions[i]; i++) {
this->functions[i] = strdup(functions[i]);
}
if (keys && events) { if (keys && events) {
this->staticData = false; this->staticData = false;
this->keys = malloc(sizeof(char*) * 15); this->functions = malloc(sizeof(char*) * size);
this->events = malloc(sizeof(int) * 15); this->keys = malloc(sizeof(char*) * size);
int i = 0; this->events = malloc(sizeof(int) * size);
while (i < 15 && functions[i]) { for (int i = 0; i < size; i++) {
this->keys[i] = strdup(keys[i]); this->functions[i] = String_copy(functions[i]);
this->keys[i] = String_copy(keys[i]);
this->events[i] = events[i]; this->events[i] = events[i];
i++;
} }
this->size = i;
} else { } else {
this->staticData = true; this->staticData = true;
this->keys = (char**) FunctionBar_FKeys; this->functions = functions ? functions : FunctionBar_FLabels;
this->keys = FunctionBar_FKeys;
this->events = FunctionBar_FEvents; this->events = FunctionBar_FEvents;
this->size = 10; assert((!functions) || this->size == 10);
} }
return this; return this;
} }
void FunctionBar_delete(Object* cast) { void FunctionBar_delete(Object* cast) {
FunctionBar* this = (FunctionBar*) cast; FunctionBar* this = (FunctionBar*) cast;
for (int i = 0; i < 15 && this->functions[i]; i++) {
free(this->functions[i]);
}
free(this->functions);
if (!this->staticData) { if (!this->staticData) {
for (int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
free(this->functions[i]);
free(this->keys[i]); free(this->keys[i]);
} }
free(this->functions);
free(this->keys); free(this->keys);
free(this->events); free(this->events);
} }
free(this); free(this);
} }
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) { void FunctionBar_setLabel(FunctionBar* this, int event, char* text) {
assert(!this->staticData);
for (int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
if (this->events[i] == event) { if (this->events[i] == event) {
free(this->functions[i]); free(this->functions[i]);
this->functions[i] = strdup(text); this->functions[i] = String_copy(text);
break; break;
} }
} }
} }
void FunctionBar_draw(const FunctionBar* this, char* buffer) { void FunctionBar_draw(FunctionBar* this, char* buffer) {
FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]); FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]);
} }
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) { void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr) {
attrset(CRT_colors[FUNCTION_BAR]); attrset(CRT_colors[FUNCTION_BAR]);
mvhline(LINES-1, 0, ' ', COLS); mvhline(LINES-1, 0, ' ', COLS);
int x = 0; int x = 0;
@ -109,18 +109,14 @@ void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) {
mvaddstr(LINES-1, x, this->functions[i]); mvaddstr(LINES-1, x, this->functions[i]);
x += strlen(this->functions[i]); x += strlen(this->functions[i]);
} }
if (buffer) { if (buffer != NULL) {
attrset(attr); attrset(attr);
mvaddstr(LINES-1, x, buffer); mvaddstr(LINES-1, x, buffer);
CRT_cursorX = x + strlen(buffer);
curs_set(1);
} else {
curs_set(0);
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
} }
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) { int FunctionBar_synthesizeEvent(FunctionBar* this, int pos) {
int x = 0; int x = 0;
for (int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
x += strlen(this->keys[i]); x += strlen(this->keys[i]);

View File

@ -4,12 +4,22 @@
#define HEADER_FunctionBar #define HEADER_FunctionBar
/* /*
htop - FunctionBar.h htop - FunctionBar.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h" #include "Object.h"
#include "CRT.h"
#include "debug.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <curses.h>
typedef struct FunctionBar_ { typedef struct FunctionBar_ {
Object super; Object super;
@ -21,18 +31,22 @@ typedef struct FunctionBar_ {
} FunctionBar; } FunctionBar;
extern ObjectClass FunctionBar_class; #ifdef DEBUG
extern char* FUNCTIONBAR_CLASS;
#else
#define FUNCTIONBAR_CLASS NULL
#endif
FunctionBar* FunctionBar_new(const char** functions, const char** keys, int* events); FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events);
void FunctionBar_delete(Object* cast); void FunctionBar_delete(Object* cast);
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text); void FunctionBar_setLabel(FunctionBar* this, int event, char* text);
void FunctionBar_draw(const FunctionBar* this, char* buffer); void FunctionBar_draw(FunctionBar* this, char* buffer);
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr); void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr);
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos); int FunctionBar_synthesizeEvent(FunctionBar* this, int pos);
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
htop - Hashtable.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
@ -8,11 +8,12 @@ in the source distribution for its full text.
#include "Hashtable.h" #include "Hashtable.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <assert.h> #include <assert.h>
/*{ #include "debug.h"
#include <stdbool.h>
/*{
typedef struct Hashtable_ Hashtable; typedef struct Hashtable_ Hashtable;
typedef void(*Hashtable_PairFunction)(int, void*, void*); typedef void(*Hashtable_PairFunction)(int, void*, void*);
@ -76,7 +77,7 @@ Hashtable* Hashtable_new(int size, bool owner) {
this = (Hashtable*) malloc(sizeof(Hashtable)); this = (Hashtable*) malloc(sizeof(Hashtable));
this->items = 0; this->items = 0;
this->size = size; this->size = size;
this->buckets = (HashtableItem**) calloc(size, sizeof(HashtableItem*)); this->buckets = (HashtableItem**) calloc(sizeof(HashtableItem*), size);
this->owner = owner; this->owner = owner;
assert(Hashtable_isConsistent(this)); assert(Hashtable_isConsistent(this));
return this; return this;

View File

@ -3,13 +3,18 @@
#ifndef HEADER_Hashtable #ifndef HEADER_Hashtable
#define HEADER_Hashtable #define HEADER_Hashtable
/* /*
htop - Hashtable.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h>
#include "debug.h"
typedef struct Hashtable_ Hashtable; typedef struct Hashtable_ Hashtable;

View File

@ -1,32 +1,17 @@
/* /*
htop - Header.c htop - Header.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Header.h" #include "Header.h"
#include "Meter.h"
#include "CRT.h" #include "debug.h"
#include "CPUMeter.h"
#include "MemoryMeter.h"
#include "SwapMeter.h"
#include "TasksMeter.h"
#include "LoadAverageMeter.h"
#include "UptimeMeter.h"
#include "BatteryMeter.h"
#include "ClockMeter.h"
#include "HostnameMeter.h"
#include "String.h"
#include <assert.h> #include <assert.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
/*{ /*{
#include "ProcessList.h"
#include "Meter.h"
typedef enum HeaderSide_ { typedef enum HeaderSide_ {
LEFT_HEADER, LEFT_HEADER,
@ -37,9 +22,9 @@ typedef struct Header_ {
Vector* leftMeters; Vector* leftMeters;
Vector* rightMeters; Vector* rightMeters;
ProcessList* pl; ProcessList* pl;
bool margin;
int height; int height;
int pad; int pad;
bool margin;
} Header; } Header;
}*/ }*/
@ -49,9 +34,9 @@ typedef struct Header_ {
#endif #endif
Header* Header_new(ProcessList* pl) { Header* Header_new(ProcessList* pl) {
Header* this = calloc(1, sizeof(Header)); Header* this = malloc(sizeof(Header));
this->leftMeters = Vector_new(Class(Meter), true, DEFAULT_SIZE); this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->rightMeters = Vector_new(Class(Meter), true, DEFAULT_SIZE); this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->margin = true; this->margin = true;
this->pl = pl; this->pl = pl;
return this; return this;
@ -71,11 +56,11 @@ void Header_createMeter(Header* this, char* name, HeaderSide side) {
char* paren = strchr(name, '('); char* paren = strchr(name, '(');
int param = 0; int param = 0;
if (paren) { if (paren) {
int ok = sscanf(paren, "(%10d)", &param); int ok = sscanf(paren, "(%d)", &param);
if (!ok) param = 0; if (!ok) param = 0;
*paren = '\0'; *paren = '\0';
} }
for (MeterClass** type = Meter_types; *type; type++) { for (MeterType** type = Meter_types; *type; type++) {
if (String_eq(name, (*type)->name)) { if (String_eq(name, (*type)->name)) {
Vector_add(meters, Meter_new(this->pl, param, *type)); Vector_add(meters, Meter_new(this->pl, param, *type));
break; break;
@ -94,7 +79,7 @@ void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side) {
Meter_setMode(meter, mode); Meter_setMode(meter, mode);
} }
Meter* Header_addMeter(Header* this, MeterClass* type, int param, HeaderSide side) { Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side) {
Vector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
@ -118,10 +103,10 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side) {
: this->rightMeters; : this->rightMeters;
Meter* meter = (Meter*) Vector_get(meters, i); Meter* meter = (Meter*) Vector_get(meters, i);
int nameLen = strlen(Meter_name(meter)); int nameLen = strlen(meter->type->name);
int len = nameLen + 100; int len = nameLen + 100;
char* name = malloc(len); char* name = malloc(len);
strncpy(name, Meter_name(meter), nameLen); strncpy(name, meter->type->name, nameLen);
name[nameLen] = '\0'; name[nameLen] = '\0';
if (meter->param) if (meter->param)
snprintf(name + nameLen, len - nameLen, "(%d)", meter->param); snprintf(name + nameLen, len - nameLen, "(%d)", meter->param);
@ -138,39 +123,19 @@ MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) {
return meter->mode; return meter->mode;
} }
void Header_defaultMeters(Header* this, int cpuCount) { void Header_defaultMeters(Header* this) {
if (cpuCount > 8) { Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(LeftCPUs2Meter))); Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(RightCPUs2Meter))); Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
} else if (cpuCount > 4) { Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(LeftCPUsMeter))); Vector_add(this->rightMeters, Meter_new(this->pl, 0, &LoadAverageMeter));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(RightCPUsMeter))); Vector_add(this->rightMeters, Meter_new(this->pl, 0, &UptimeMeter));
} else {
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(AllCPUsMeter)));
}
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(MemoryMeter)));
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(SwapMeter)));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(TasksMeter)));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(LoadAverageMeter)));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(UptimeMeter)));
} }
void Header_reinit(Header* this) { void Header_draw(Header* this) {
for (int i = 0; i < Vector_size(this->leftMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->leftMeters, i);
if (Meter_initFn(meter))
Meter_init(meter);
}
for (int i = 0; i < Vector_size(this->rightMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->rightMeters, i);
if (Meter_initFn(meter))
Meter_init(meter);
}
}
void Header_draw(const Header* this) {
int height = this->height; int height = this->height;
int pad = this->pad; int pad = this->pad;
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
mvhline(y, 0, ' ', COLS); mvhline(y, 0, ' ', COLS);

View File

@ -4,14 +4,17 @@
#define HEADER_Header #define HEADER_Header
/* /*
htop - Header.h htop - Header.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ProcessList.h"
#include "Meter.h" #include "Meter.h"
#include "debug.h"
#include <assert.h>
typedef enum HeaderSide_ { typedef enum HeaderSide_ {
LEFT_HEADER, LEFT_HEADER,
RIGHT_HEADER RIGHT_HEADER
@ -21,9 +24,9 @@ typedef struct Header_ {
Vector* leftMeters; Vector* leftMeters;
Vector* rightMeters; Vector* rightMeters;
ProcessList* pl; ProcessList* pl;
bool margin;
int height; int height;
int pad; int pad;
bool margin;
} Header; } Header;
@ -39,7 +42,7 @@ void Header_createMeter(Header* this, char* name, HeaderSide side);
void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side); void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side);
Meter* Header_addMeter(Header* this, MeterClass* type, int param, HeaderSide side); Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side);
int Header_size(Header* this, HeaderSide side); int Header_size(Header* this, HeaderSide side);
@ -47,11 +50,9 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side);
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side); MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side);
void Header_defaultMeters(Header* this, int cpuCount); void Header_defaultMeters(Header* this);
void Header_reinit(Header* this); void Header_draw(Header* this);
void Header_draw(const Header* this);
int Header_calculateHeight(Header* this); int Header_calculateHeight(Header* this);

View File

@ -1,39 +0,0 @@
/*
htop - HostnameMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "HostnameMeter.h"
#include "CRT.h"
#include <unistd.h>
/*{
#include "Meter.h"
}*/
int HostnameMeter_attributes[] = {
HOSTNAME
};
static void HostnameMeter_setValues(Meter* this, char* buffer, int size) {
(void) this;
gethostname(buffer, size-1);
}
MeterClass HostnameMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.setValues = HostnameMeter_setValues,
.defaultMode = TEXT_METERMODE,
.total = 100.0,
.attributes = HostnameMeter_attributes,
.name = "Hostname",
.uiName = "Hostname",
.caption = "Hostname: ",
};

View File

@ -1,18 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_HostnameMeter
#define HEADER_HostnameMeter
/*
htop - HostnameMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
extern int HostnameMeter_attributes[];
extern MeterClass HostnameMeter_class;
#endif

View File

@ -1,41 +0,0 @@
/*
htop - IOPriority.c
(C) 2004-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
Based on ionice,
Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
Released under the terms of the GNU General Public License version 2
*/
#include "IOPriority.h"
/*{
enum {
IOPRIO_CLASS_NONE,
IOPRIO_CLASS_RT,
IOPRIO_CLASS_BE,
IOPRIO_CLASS_IDLE,
};
#define IOPRIO_WHO_PROCESS 1
#define IOPRIO_CLASS_SHIFT (13)
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPriority_class(ioprio_) ((int) ((ioprio_) >> IOPRIO_CLASS_SHIFT) )
#define IOPriority_data(ioprio_) ((int) ((ioprio_) & IOPRIO_PRIO_MASK) )
typedef int IOPriority;
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | data_)
#define IOPriority_error 0xffffffff
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 0)
}*/

View File

@ -1,43 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_IOPriority
#define HEADER_IOPriority
/*
htop - IOPriority.h
(C) 2004-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
Based on ionice,
Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
Released under the terms of the GNU General Public License version 2
*/
enum {
IOPRIO_CLASS_NONE,
IOPRIO_CLASS_RT,
IOPRIO_CLASS_BE,
IOPRIO_CLASS_IDLE,
};
#define IOPRIO_WHO_PROCESS 1
#define IOPRIO_CLASS_SHIFT (13)
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPriority_class(ioprio_) ((int) ((ioprio_) >> IOPRIO_CLASS_SHIFT) )
#define IOPriority_data(ioprio_) ((int) ((ioprio_) & IOPRIO_PRIO_MASK) )
typedef int IOPriority;
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | data_)
#define IOPriority_error 0xffffffff
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 0)
#endif

View File

@ -1,43 +0,0 @@
/*
htop - IOPriorityPanel.c
(C) 2004-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "IOPriorityPanel.h"
/*{
#include "Panel.h"
#include "IOPriority.h"
#include "ListItem.h"
}*/
Panel* IOPriorityPanel_new(IOPriority currPrio) {
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem));
Panel_setHeader(this, "IO Priority:");
Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None));
if (currPrio == IOPriority_None) Panel_setSelected(this, 0);
struct { int klass; const char* name; } classes[] = {
{ .klass = IOPRIO_CLASS_RT, .name = "Realtime" },
{ .klass = IOPRIO_CLASS_BE, .name = "Best-effort" },
{ .klass = 0, .name = NULL }
};
for (int c = 0; classes[c].name; c++) {
for (int i = 0; i < 8; i++) {
char name[50];
snprintf(name, sizeof(name)-1, "%s %d %s", classes[c].name, i, i == 0 ? "(High)" : (i == 7 ? "(Low)" : ""));
IOPriority ioprio = IOPriority_tuple(classes[c].klass, i);
Panel_add(this, (Object*) ListItem_new(name, ioprio));
if (currPrio == ioprio) Panel_setSelected(this, Panel_size(this) - 1);
}
}
Panel_add(this, (Object*) ListItem_new("Idle", IOPriority_Idle));
if (currPrio == IOPriority_Idle) Panel_setSelected(this, Panel_size(this) - 1);
return this;
}
IOPriority IOPriorityPanel_getIOPriority(Panel* this) {
return (IOPriority) ( ((ListItem*) Panel_getSelected(this))->key );
}

View File

@ -1,20 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_IOPriorityPanel
#define HEADER_IOPriorityPanel
/*
htop - IOPriorityPanel.h
(C) 2004-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "IOPriority.h"
#include "ListItem.h"
Panel* IOPriorityPanel_new(IOPriority currPrio);
IOPriority IOPriorityPanel_getIOPriority(Panel* this);
#endif

213
IncSet.c
View File

@ -1,213 +0,0 @@
/*
htop - IncSet.c
(C) 2005-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "IncSet.h"
#include "String.h"
#include "Panel.h"
#include "ListItem.h"
#include "CRT.h"
#include <string.h>
#include <stdlib.h>
/*{
#include "FunctionBar.h"
#include "Panel.h"
#include <stdbool.h>
#define INCMODE_MAX 40
typedef enum {
INC_SEARCH = 0,
INC_FILTER = 1
} IncType;
#define IncSet_filter(inc_) (inc_->filtering ? inc_->modes[INC_FILTER].buffer : NULL)
typedef struct IncMode_ {
char buffer[INCMODE_MAX+1];
int index;
FunctionBar* bar;
bool isFilter;
} IncMode;
typedef struct IncSet_ {
IncMode modes[2];
IncMode* active;
FunctionBar* bar;
FunctionBar* defaultBar;
bool filtering;
} IncSet;
typedef const char* (*IncMode_GetPanelValue)(Panel*, int);
}*/
static void IncMode_reset(IncMode* mode) {
mode->index = 0;
mode->buffer[0] = 0;
}
static const char* searchFunctions[] = {"Next ", "Cancel ", " Search: ", NULL};
static const char* searchKeys[] = {"F3", "Esc", " "};
static int searchEvents[] = {KEY_F(3), 27, ERR};
static inline void IncMode_initSearch(IncMode* search) {
memset(search, 0, sizeof(IncMode));
search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents);
search->isFilter = false;
}
static const char* filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL};
static const char* filterKeys[] = {"Enter", "Esc", " "};
static int filterEvents[] = {13, 27, ERR};
static inline void IncMode_initFilter(IncMode* filter) {
memset(filter, 0, sizeof(IncMode));
filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents);
filter->isFilter = true;
}
static inline void IncMode_done(IncMode* mode) {
FunctionBar_delete((Object*)mode->bar);
}
IncSet* IncSet_new(FunctionBar* bar) {
IncSet* this = calloc(1, sizeof(IncSet));
IncMode_initSearch(&(this->modes[INC_SEARCH]));
IncMode_initFilter(&(this->modes[INC_FILTER]));
this->active = NULL;
this->filtering = false;
this->bar = bar;
this->defaultBar = bar;
return this;
}
void IncSet_delete(IncSet* this) {
IncMode_done(&(this->modes[0]));
IncMode_done(&(this->modes[1]));
free(this);
}
static void updateWeakPanel(IncSet* this, Panel* panel, Vector* lines) {
Object* selected = Panel_getSelected(panel);
Panel_prune(panel);
if (this->filtering) {
int n = 0;
const char* incFilter = this->modes[INC_FILTER].buffer;
for (int i = 0; i < Vector_size(lines); i++) {
ListItem* line = (ListItem*)Vector_get(lines, i);
if (String_contains_i(line->value, incFilter)) {
Panel_add(panel, (Object*)line);
if (selected == (Object*)line) Panel_setSelected(panel, n);
n++;
}
}
} else {
for (int i = 0; i < Vector_size(lines); i++) {
Object* line = Vector_get(lines, i);
Panel_add(panel, line);
if (selected == line) Panel_setSelected(panel, i);
}
}
}
static void search(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) {
int size = Panel_size(panel);
bool found = false;
for (int i = 0; i < size; i++) {
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
found = true;
break;
}
}
if (found)
FunctionBar_draw(mode->bar, mode->buffer);
else
FunctionBar_drawAttr(mode->bar, mode->buffer, CRT_colors[FAILED_SEARCH]);
}
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
if (ch == ERR)
return true;
IncMode* mode = this->active;
int size = Panel_size(panel);
bool filterChange = false;
bool doSearch = true;
if (ch == KEY_F(3)) {
if (size == 0) return true;
int here = Panel_getSelectedIndex(panel);
int i = here;
for(;;) {
i++;
if (i == size) i = 0;
if (i == here) break;
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
break;
}
}
doSearch = false;
} else if (isprint((char)ch) && (mode->index < INCMODE_MAX)) {
mode->buffer[mode->index] = ch;
mode->index++;
mode->buffer[mode->index] = 0;
if (mode->isFilter) {
filterChange = true;
if (mode->index == 1) this->filtering = true;
}
} else if ((ch == KEY_BACKSPACE || ch == 127) && (mode->index > 0)) {
mode->index--;
mode->buffer[mode->index] = 0;
if (mode->isFilter) {
filterChange = true;
if (mode->index == 0) {
this->filtering = false;
IncMode_reset(mode);
}
}
} else {
if (mode->isFilter) {
filterChange = true;
if (ch == 27) {
this->filtering = false;
IncMode_reset(mode);
}
} else {
IncMode_reset(mode);
}
this->active = NULL;
this->bar = this->defaultBar;
FunctionBar_draw(this->defaultBar, NULL);
doSearch = false;
}
if (doSearch) {
search(mode, panel, getPanelValue);
}
if (filterChange && lines) {
updateWeakPanel(this, panel, lines);
}
return filterChange;
}
const char* IncSet_getListItemValue(Panel* panel, int i) {
ListItem* l = (ListItem*) Panel_get(panel, i);
if (l)
return l->value;
return "";
}
void IncSet_activate(IncSet* this, IncType type) {
this->active = &(this->modes[type]);
this->bar = this->active->bar;
FunctionBar_draw(this->active->bar, this->active->buffer);
}
void IncSet_drawBar(IncSet* this) {
FunctionBar_draw(this->bar, this->active ? this->active->buffer : NULL);
}

View File

@ -1,56 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_IncSet
#define HEADER_IncSet
/*
htop - IncSet.h
(C) 2005-2012 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "FunctionBar.h"
#include "Panel.h"
#include <stdbool.h>
#define INCMODE_MAX 40
typedef enum {
INC_SEARCH = 0,
INC_FILTER = 1
} IncType;
#define IncSet_filter(inc_) (inc_->filtering ? inc_->modes[INC_FILTER].buffer : NULL)
typedef struct IncMode_ {
char buffer[INCMODE_MAX+1];
int index;
FunctionBar* bar;
bool isFilter;
} IncMode;
typedef struct IncSet_ {
IncMode modes[2];
IncMode* active;
FunctionBar* bar;
FunctionBar* defaultBar;
bool filtering;
} IncSet;
typedef const char* (*IncMode_GetPanelValue)(Panel*, int);
IncSet* IncSet_new(FunctionBar* bar);
void IncSet_delete(IncSet* this);
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
const char* IncSet_getListItemValue(Panel* panel, int i);
void IncSet_activate(IncSet* this, IncType type);
void IncSet_drawBar(IncSet* this);
#endif

View File

@ -1,22 +1,19 @@
/* /*
htop - ListItem.c htop - ListItem.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ListItem.h" #include "ListItem.h"
#include "CRT.h"
#include "String.h" #include "String.h"
#include "Object.h"
#include "RichString.h" #include "RichString.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <stdlib.h> #include "debug.h"
/*{ /*{
#include "Object.h"
typedef struct ListItem_ { typedef struct ListItem_ {
Object super; Object super;
@ -26,6 +23,12 @@ typedef struct ListItem_ {
}*/ }*/
#ifdef DEBUG
char* LISTITEM_CLASS = "ListItem";
#else
#define LISTITEM_CLASS NULL
#endif
static void ListItem_delete(Object* cast) { static void ListItem_delete(Object* cast) {
ListItem* this = (ListItem*)cast; ListItem* this = (ListItem*)cast;
free(this->value); free(this->value);
@ -35,34 +38,27 @@ static void ListItem_delete(Object* cast) {
static void ListItem_display(Object* cast, RichString* out) { static void ListItem_display(Object* cast, RichString* out) {
ListItem* this = (ListItem*)cast; ListItem* this = (ListItem*)cast;
assert (this != NULL); assert (this != NULL);
/*
int len = strlen(this->value)+1; int len = strlen(this->value)+1;
char buffer[len+1]; char buffer[len+1];
snprintf(buffer, len, "%s", this->value); snprintf(buffer, len, "%s", this->value);
*/ RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer);
RichString_write(out, CRT_colors[DEFAULT_COLOR], this->value/*buffer*/);
} }
ObjectClass ListItem_class = { ListItem* ListItem_new(char* value, int key) {
.display = ListItem_display, ListItem* this = malloc(sizeof(ListItem));
.delete = ListItem_delete, Object_setClass(this, LISTITEM_CLASS);
.compare = ListItem_compare ((Object*)this)->display = ListItem_display;
}; ((Object*)this)->delete = ListItem_delete;
this->value = String_copy(value);
ListItem* ListItem_new(const char* value, int key) {
ListItem* this = AllocThis(ListItem);
this->value = strdup(value);
this->key = key; this->key = key;
return this; return this;
} }
void ListItem_append(ListItem* this, const char* text) { void ListItem_append(ListItem* this, char* text) {
int oldLen = strlen(this->value); char* buf = malloc(strlen(this->value) + strlen(text) + 1);
int textLen = strlen(text); sprintf(buf, "%s%s", this->value, text);
int newLen = strlen(this->value) + textLen; free(this->value);
this->value = realloc(this->value, newLen + 1); this->value = buf;
memcpy(this->value + oldLen, text, textLen);
this->value[newLen] = '\0';
} }
const char* ListItem_getRef(ListItem* this) { const char* ListItem_getRef(ListItem* this) {

View File

@ -4,12 +4,18 @@
#define HEADER_ListItem #define HEADER_ListItem
/* /*
htop - ListItem.h htop - ListItem.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "String.h"
#include "Object.h" #include "Object.h"
#include "RichString.h"
#include <string.h>
#include "debug.h"
typedef struct ListItem_ { typedef struct ListItem_ {
Object super; Object super;
@ -18,11 +24,15 @@ typedef struct ListItem_ {
} ListItem; } ListItem;
extern ObjectClass ListItem_class; #ifdef DEBUG
extern char* LISTITEM_CLASS;
#else
#define LISTITEM_CLASS NULL
#endif
ListItem* ListItem_new(const char* value, int key); ListItem* ListItem_new(char* value, int key);
void ListItem_append(ListItem* this, const char* text); void ListItem_append(ListItem* this, char* text);
const char* ListItem_getRef(ListItem* this); const char* ListItem_getRef(ListItem* this);

View File

@ -1,19 +1,16 @@
/* /*
htop - LoadAverageMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "LoadAverageMeter.h" #include "LoadAverageMeter.h"
#include "CRT.h"
#include <assert.h>
/*{
#include "Meter.h" #include "Meter.h"
}*/
#include <curses.h>
#include "debug.h"
int LoadAverageMeter_attributes[] = { int LoadAverageMeter_attributes[] = {
LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE
@ -23,16 +20,13 @@ int LoadMeter_attributes[] = { LOAD };
static inline void LoadAverageMeter_scan(double* one, double* five, double* fifteen) { static inline void LoadAverageMeter_scan(double* one, double* five, double* fifteen) {
int activeProcs, totalProcs, lastProc; int activeProcs, totalProcs, lastProc;
*one = 0; *five = 0; *fifteen = 0;
FILE *fd = fopen(PROCDIR "/loadavg", "r"); FILE *fd = fopen(PROCDIR "/loadavg", "r");
if (fd) { int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
int total = fscanf(fd, "%32lf %32lf %32lf %32d/%32d %32d", one, five, fifteen,
&activeProcs, &totalProcs, &lastProc); &activeProcs, &totalProcs, &lastProc);
(void) total; (void) read;
assert(total == 6); assert(read == 6);
fclose(fd); fclose(fd);
} }
}
static void LoadAverageMeter_setValues(Meter* this, char* buffer, int size) { static void LoadAverageMeter_setValues(Meter* this, char* buffer, int size) {
LoadAverageMeter_scan(&this->values[2], &this->values[1], &this->values[0]); LoadAverageMeter_scan(&this->values[2], &this->values[1], &this->values[0]);
@ -42,8 +36,9 @@ static void LoadAverageMeter_setValues(Meter* this, char* buffer, int size) {
static void LoadAverageMeter_display(Object* cast, RichString* out) { static void LoadAverageMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
char buffer[20]; char buffer[20];
RichString_init(out);
sprintf(buffer, "%.2f ", this->values[2]); sprintf(buffer, "%.2f ", this->values[2]);
RichString_write(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer); RichString_append(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
sprintf(buffer, "%.2f ", this->values[1]); sprintf(buffer, "%.2f ", this->values[1]);
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer); RichString_append(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer);
sprintf(buffer, "%.2f ", this->values[0]); sprintf(buffer, "%.2f ", this->values[0]);
@ -62,19 +57,16 @@ static void LoadMeter_setValues(Meter* this, char* buffer, int size) {
static void LoadMeter_display(Object* cast, RichString* out) { static void LoadMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
char buffer[20]; char buffer[20];
RichString_init(out);
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]); sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
RichString_write(out, CRT_colors[LOAD], buffer); RichString_append(out, CRT_colors[LOAD], buffer);
} }
MeterClass LoadAverageMeter_class = { MeterType LoadAverageMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = LoadAverageMeter_display,
},
.setValues = LoadAverageMeter_setValues, .setValues = LoadAverageMeter_setValues,
.defaultMode = TEXT_METERMODE, .display = LoadAverageMeter_display,
.maxItems = 3, .mode = TEXT_METERMODE,
.items = 3,
.total = 100.0, .total = 100.0,
.attributes = LoadAverageMeter_attributes, .attributes = LoadAverageMeter_attributes,
.name = "LoadAverage", .name = "LoadAverage",
@ -82,14 +74,11 @@ MeterClass LoadAverageMeter_class = {
.caption = "Load average: " .caption = "Load average: "
}; };
MeterClass LoadMeter_class = { MeterType LoadMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = LoadMeter_display,
},
.setValues = LoadMeter_setValues, .setValues = LoadMeter_setValues,
.defaultMode = TEXT_METERMODE, .display = LoadMeter_display,
.mode = TEXT_METERMODE,
.items = 1,
.total = 100.0, .total = 100.0,
.attributes = LoadMeter_attributes, .attributes = LoadMeter_attributes,
.name = "Load", .name = "Load",

View File

@ -3,20 +3,24 @@
#ifndef HEADER_LoadAverageMeter #ifndef HEADER_LoadAverageMeter
#define HEADER_LoadAverageMeter #define HEADER_LoadAverageMeter
/* /*
htop - LoadAverageMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include <curses.h>
#include "debug.h"
extern int LoadAverageMeter_attributes[]; extern int LoadAverageMeter_attributes[];
extern int LoadMeter_attributes[]; extern int LoadMeter_attributes[];
extern MeterClass LoadAverageMeter_class; extern MeterType LoadAverageMeter;
extern MeterClass LoadMeter_class; extern MeterType LoadMeter;
#endif #endif

View File

@ -1,5 +1,5 @@
ACLOCAL_AMFLAGS = -I m4 SUBDIRS = plpa-1.1
bin_PROGRAMS = htop bin_PROGRAMS = htop
dist_man_MANS = htop.1 dist_man_MANS = htop.1
@ -10,40 +10,46 @@ applications_DATA = htop.desktop
pixmapdir = $(datadir)/pixmaps pixmapdir = $(datadir)/pixmaps
pixmap_DATA = htop.png pixmap_DATA = htop.png
htop_CFLAGS = -pedantic -Wall -Wextra -std=c99 -rdynamic -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\" htop_CFLAGS = -pedantic -Wall -std=c99 -D_XOPEN_SOURCE_EXTENDED
AM_CPPFLAGS = -DNDEBUG AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \ myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \
ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c \ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c DebugMemory.c \
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \ DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
IOPriorityPanel.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \ SignalItem.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c
HostnameMeter.c OpenFilesScreen.c Affinity.c IOPriority.c IncSet.c
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \ myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
IOPriorityPanel.h CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \ CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \ Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \ Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
ScreenManager.h Settings.h SignalsPanel.h String.h SwapMeter.h TasksMeter.h \ ScreenManager.h Settings.h SignalItem.h SignalsPanel.h String.h \
TraceScreen.h UptimeMeter.h UsersTable.h Vector.h Process.h AffinityPanel.h \ SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
HostnameMeter.h OpenFilesScreen.h Affinity.h IOPriority.h IncSet.h Process.h AffinityPanel.h
SUFFIXES = .h SUFFIXES = .h
BUILT_SOURCES = $(myhtopheaders) BUILT_SOURCES = $(myhtopheaders)
htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h debug.h
htop_LDADD = $(top_builddir)/plpa-1.1/src/libplpa_included.la
profile: profile:
$(MAKE) all CFLAGS="-pg" AM_CPPFLAGS="-pg -O2 -DNDEBUG" $(MAKE) all CFLAGS="-pg -O2"
debug: debug:
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DDEBUG" $(MAKE) all CFLAGS="-ggdb -DDEBUG"
hardened-debug:
$(MAKE) all CFLAGS="-ggdb -DDEBUG" LDFLAGS="-nopie"
debuglite:
$(MAKE) all CFLAGS="-ggdb -DDEBUGLITE"
.c.h: .c.h:
@srcdir@/scripts/MakeHeader.py $< scripts/MakeHeader.py $<
cppcheck:
cppcheck -q -v . --enable=all -DHAVE_CGROUP -DHAVE_OPENVZ -DHAVE_TASKSTATS

View File

@ -1,24 +1,23 @@
/* /*
htop - MemoryMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "MemoryMeter.h" #include "MemoryMeter.h"
#include "Meter.h"
#include "CRT.h"
#include "ProcessList.h" #include "ProcessList.h"
#include <stdlib.h> #include <stdlib.h>
#include <curses.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
/*{ #include "debug.h"
#include "Meter.h" #include <assert.h>
}*/
int MemoryMeter_attributes[] = { int MemoryMeter_attributes[] = {
MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE
@ -39,12 +38,13 @@ static void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
static void MemoryMeter_display(Object* cast, RichString* out) { static void MemoryMeter_display(Object* cast, RichString* out) {
char buffer[50]; char buffer[50];
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
int k = 1024; const char* format = "%ldM "; int div = 1024; char* format = "%ldM ";
long int totalMem = this->total / k; long int totalMem = this->total / div;
long int usedMem = this->values[0] / k; long int usedMem = this->values[0] / div;
long int buffersMem = this->values[1] / k; long int buffersMem = this->values[1] / div;
long int cachedMem = this->values[2] / k; long int cachedMem = this->values[2] / div;
RichString_write(out, CRT_colors[METER_TEXT], ":"); RichString_init(out);
RichString_append(out, CRT_colors[METER_TEXT], ":");
sprintf(buffer, format, totalMem); sprintf(buffer, format, totalMem);
RichString_append(out, CRT_colors[METER_VALUE], buffer); RichString_append(out, CRT_colors[METER_VALUE], buffer);
sprintf(buffer, format, usedMem); sprintf(buffer, format, usedMem);
@ -52,21 +52,17 @@ static void MemoryMeter_display(Object* cast, RichString* out) {
RichString_append(out, CRT_colors[MEMORY_USED], buffer); RichString_append(out, CRT_colors[MEMORY_USED], buffer);
sprintf(buffer, format, buffersMem); sprintf(buffer, format, buffersMem);
RichString_append(out, CRT_colors[METER_TEXT], "buffers:"); RichString_append(out, CRT_colors[METER_TEXT], "buffers:");
RichString_append(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer); RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer);
sprintf(buffer, format, cachedMem); sprintf(buffer, format, cachedMem);
RichString_append(out, CRT_colors[METER_TEXT], "cache:"); RichString_append(out, CRT_colors[METER_TEXT], "cache:");
RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); RichString_append(out, CRT_colors[MEMORY_CACHE], buffer);
} }
MeterClass MemoryMeter_class = { MeterType MemoryMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = MemoryMeter_display,
},
.setValues = MemoryMeter_setValues, .setValues = MemoryMeter_setValues,
.defaultMode = BAR_METERMODE, .display = MemoryMeter_display,
.maxItems = 3, .mode = BAR_METERMODE,
.items = 3,
.total = 100.0, .total = 100.0,
.attributes = MemoryMeter_attributes, .attributes = MemoryMeter_attributes,
"Memory", "Memory",

View File

@ -3,16 +3,27 @@
#ifndef HEADER_MemoryMeter #ifndef HEADER_MemoryMeter
#define HEADER_MemoryMeter #define HEADER_MemoryMeter
/* /*
htop - MemoryMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include <sys/param.h>
#include "debug.h"
#include <assert.h>
extern int MemoryMeter_attributes[]; extern int MemoryMeter_attributes[];
extern MeterClass MemoryMeter_class; extern MeterType MemoryMeter;
#endif #endif

433
Meter.c
View File

@ -1,11 +1,94 @@
/* /*
htop - Meter.c htop - Meter.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "Meter.h" #include "Meter.h"
#include "Object.h"
#include "CRT.h"
#include "ListItem.h"
#include "String.h"
#include "ProcessList.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#ifndef USE_FUNKY_MODES
#define USE_FUNKY_MODES 1
#endif
#define METER_BUFFER_LEN 128
/*{
typedef struct Meter_ Meter;
typedef struct MeterType_ MeterType;
typedef struct MeterMode_ MeterMode;
typedef void(*MeterType_Init)(Meter*);
typedef void(*MeterType_Done)(Meter*);
typedef void(*MeterType_SetMode)(Meter*, int);
typedef void(*Meter_SetValues)(Meter*, char*, int);
typedef void(*Meter_Draw)(Meter*, int, int, int);
struct MeterMode_ {
Meter_Draw draw;
char* uiName;
int h;
};
struct MeterType_ {
Meter_SetValues setValues;
Object_Display display;
int mode;
int items;
double total;
int* attributes;
char* name;
char* uiName;
char* caption;
MeterType_Init init;
MeterType_Done done;
MeterType_SetMode setMode;
Meter_Draw draw;
};
struct Meter_ {
Object super;
char* caption;
MeterType* type;
int mode;
int param;
Meter_Draw draw;
void* drawBuffer;
int h;
ProcessList* pl;
double* values;
double total;
};
typedef enum {
CUSTOM_METERMODE = 0,
BAR_METERMODE,
TEXT_METERMODE,
#ifdef USE_FUNKY_MODES
GRAPH_METERMODE,
LED_METERMODE,
#endif
LAST_METERMODE
} MeterModeId;
}*/
#include "CPUMeter.h" #include "CPUMeter.h"
#include "MemoryMeter.h" #include "MemoryMeter.h"
@ -13,105 +96,7 @@ in the source distribution for its full text.
#include "TasksMeter.h" #include "TasksMeter.h"
#include "LoadAverageMeter.h" #include "LoadAverageMeter.h"
#include "UptimeMeter.h" #include "UptimeMeter.h"
#include "BatteryMeter.h"
#include "ClockMeter.h" #include "ClockMeter.h"
#include "HostnameMeter.h"
#include "RichString.h"
#include "Object.h"
#include "CRT.h"
#include "String.h"
#include "ListItem.h"
#include "Settings.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <sys/time.h>
#define METER_BUFFER_LEN 128
/*{
#include "ListItem.h"
#include "ProcessList.h"
typedef struct Meter_ Meter;
typedef void(*Meter_Init)(Meter*);
typedef void(*Meter_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int);
typedef void(*Meter_SetValues)(Meter*, char*, int);
typedef void(*Meter_Draw)(Meter*, int, int, int);
typedef struct MeterClass_ {
ObjectClass super;
const Meter_Init init;
const Meter_Done done;
const Meter_UpdateMode updateMode;
const Meter_Draw draw;
const Meter_SetValues setValues;
const int defaultMode;
const double total;
const int* attributes;
const char* name;
const char* uiName;
const char* caption;
const char maxItems;
char curItems;
} MeterClass;
#define As_Meter(this_) ((MeterClass*)((this_)->super.klass))
#define Meter_initFn(this_) As_Meter(this_)->init
#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_))
#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_))
#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode
#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_)
#define Meter_drawFn(this_) As_Meter(this_)->draw
#define Meter_doneFn(this_) As_Meter(this_)->done
#define Meter_setValues(this_, c_, i_) As_Meter(this_)->setValues((Meter*)(this_), c_, i_)
#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode
#define Meter_getItems(this_) As_Meter(this_)->curItems
#define Meter_setItems(this_, n_) As_Meter(this_)->curItems = (n_)
#define Meter_attributes(this_) As_Meter(this_)->attributes
#define Meter_name(this_) As_Meter(this_)->name
#define Meter_uiName(this_) As_Meter(this_)->uiName
struct Meter_ {
Object super;
Meter_Draw draw;
char* caption;
int mode;
int param;
void* drawData;
int h;
ProcessList* pl;
double* values;
double total;
};
typedef struct MeterMode_ {
Meter_Draw draw;
const char* uiName;
int h;
} MeterMode;
typedef enum {
CUSTOM_METERMODE = 0,
BAR_METERMODE,
TEXT_METERMODE,
GRAPH_METERMODE,
LED_METERMODE,
LAST_METERMODE
} MeterModeId;
typedef struct GraphData_ {
struct timeval time;
double values[METER_BUFFER_LEN];
} GraphData;
}*/
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
@ -120,77 +105,71 @@ typedef struct GraphData_ {
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
MeterClass Meter_class = { #ifdef DEBUG
.super = { char* METER_CLASS = "Meter";
.extends = Class(Object) #else
} #define METER_CLASS NULL
}; #endif
MeterClass* Meter_types[] = { MeterType* Meter_types[] = {
&CPUMeter_class, &CPUMeter,
&ClockMeter_class, &ClockMeter,
&LoadAverageMeter_class, &LoadAverageMeter,
&LoadMeter_class, &LoadMeter,
&MemoryMeter_class, &MemoryMeter,
&SwapMeter_class, &SwapMeter,
&TasksMeter_class, &TasksMeter,
&UptimeMeter_class, &UptimeMeter,
&BatteryMeter_class, &AllCPUsMeter,
&HostnameMeter_class,
&AllCPUsMeter_class,
&AllCPUs2Meter_class,
&LeftCPUsMeter_class,
&RightCPUsMeter_class,
&LeftCPUs2Meter_class,
&RightCPUs2Meter_class,
&BlankMeter_class,
NULL NULL
}; };
Meter* Meter_new(ProcessList* pl, int param, MeterClass* type) { static RichString Meter_stringBuffer;
Meter* this = calloc(1, sizeof(Meter));
Object_setClass(this, type); Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
Meter* this = calloc(sizeof(Meter), 1);
Object_setClass(this, METER_CLASS);
((Object*)this)->delete = Meter_delete;
((Object*)this)->display = type->display;
this->h = 1; this->h = 1;
this->type = type;
this->param = param; this->param = param;
this->pl = pl; this->pl = pl;
char maxItems = type->maxItems; this->values = calloc(sizeof(double), type->items);
if (maxItems == 0) {
maxItems = 1;
}
type->curItems = maxItems;
this->values = calloc(maxItems, sizeof(double));
this->total = type->total; this->total = type->total;
this->caption = strdup(type->caption); this->caption = strdup(type->caption);
if (Meter_initFn(this)) Meter_setMode(this, type->mode);
Meter_init(this); if (this->type->init)
Meter_setMode(this, type->defaultMode); this->type->init(this);
return this; return this;
} }
void Meter_delete(Object* cast) { void Meter_delete(Object* cast) {
if (!cast)
return;
Meter* this = (Meter*) cast; Meter* this = (Meter*) cast;
if (Meter_doneFn(this)) { assert (this != NULL);
Meter_done(this); if (this->type->done) {
this->type->done(this);
} }
if (this->drawData) if (this->drawBuffer)
free(this->drawData); free(this->drawBuffer);
free(this->caption); free(this->caption);
free(this->values); free(this->values);
free(this); free(this);
} }
void Meter_setCaption(Meter* this, const char* caption) { void Meter_setCaption(Meter* this, char* caption) {
free(this->caption); free(this->caption);
this->caption = strdup(caption); this->caption = strdup(caption);
} }
static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) { static inline void Meter_displayToStringBuffer(Meter* this, char* buffer) {
if (Object_displayFn(this)) { MeterType* type = this->type;
Object_display(this, out); Object_Display display = ((Object*)this)->display;
if (display) {
display((Object*)this, &Meter_stringBuffer);
} else { } else {
RichString_write(out, CRT_colors[Meter_attributes(this)[0]], buffer); RichString_initVal(Meter_stringBuffer);
RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer);
} }
} }
@ -200,15 +179,15 @@ void Meter_setMode(Meter* this, int modeIndex) {
if (!modeIndex) if (!modeIndex)
modeIndex = 1; modeIndex = 1;
assert(modeIndex < LAST_METERMODE); assert(modeIndex < LAST_METERMODE);
if (Meter_defaultMode(this) == CUSTOM_METERMODE) { if (this->type->mode == 0) {
this->draw = Meter_drawFn(this); this->draw = this->type->draw;
if (Meter_updateModeFn(this)) if (this->type->setMode)
Meter_updateMode(this, modeIndex); this->type->setMode(this, modeIndex);
} else { } else {
assert(modeIndex >= 1); assert(modeIndex >= 1);
if (this->drawData) if (this->drawBuffer)
free(this->drawData); free(this->drawBuffer);
this->drawData = NULL; this->drawBuffer = NULL;
MeterMode* mode = Meter_modes[modeIndex]; MeterMode* mode = Meter_modes[modeIndex];
this->draw = mode->draw; this->draw = mode->draw;
@ -218,6 +197,7 @@ void Meter_setMode(Meter* this, int modeIndex) {
} }
ListItem* Meter_toListItem(Meter* this) { ListItem* Meter_toListItem(Meter* this) {
MeterType* type = this->type;
char mode[21]; char mode[21];
if (this->mode) if (this->mode)
snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName); snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName);
@ -229,27 +209,26 @@ ListItem* Meter_toListItem(Meter* this) {
else else
number[0] = '\0'; number[0] = '\0';
char buffer[51]; char buffer[51];
snprintf(buffer, 50, "%s%s%s", Meter_uiName(this), number, mode); snprintf(buffer, 50, "%s%s%s", type->uiName, number, mode);
return ListItem_new(buffer, 0); return ListItem_new(buffer, 0);
} }
/* ---------- TextMeterMode ---------- */ /* ---------- TextMeterMode ---------- */
static void TextMeterMode_draw(Meter* this, int x, int y, int w) { static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
(void) w;
attrset(CRT_colors[METER_TEXT]); attrset(CRT_colors[METER_TEXT]);
mvaddstr(y, x, this->caption); mvaddstr(y, x, this->caption);
int captionLen = strlen(this->caption); int captionLen = strlen(this->caption);
w -= captionLen;
x += captionLen; x += captionLen;
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]);
RichString_begin(out); RichString_printVal(Meter_stringBuffer, y, x);
Meter_displayBuffer(this, buffer, &out);
RichString_printVal(out, y, x);
RichString_end(out);
} }
/* ---------- BarMeterMode ---------- */ /* ---------- BarMeterMode ---------- */
@ -257,13 +236,14 @@ static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
static char BarMeterMode_characters[] = "|#*@$%&"; static char BarMeterMode_characters[] = "|#*@$%&";
static void BarMeterMode_draw(Meter* this, int x, int y, int w) { static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
w -= 2; w -= 2;
attrset(CRT_colors[METER_TEXT]); attrset(CRT_colors[METER_TEXT]);
int captionLen = 3; mvaddstr(y, x, this->caption);
mvaddnstr(y, x, this->caption, captionLen); int captionLen = strlen(this->caption);
x += captionLen; x += captionLen;
w -= captionLen; w -= captionLen;
attrset(CRT_colors[BAR_BORDER]); attrset(CRT_colors[BAR_BORDER]);
@ -272,24 +252,18 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
w--; w--;
x++; x++;
char bar[w];
if (w < 1) {
attrset(CRT_colors[RESET_COLOR]);
return;
}
char bar[w + 1];
int blockSizes[10]; int blockSizes[10];
for (int i = 0; i < w; i++) for (int i = 0; i < w; i++)
bar[i] = ' '; bar[i] = ' ';
const size_t barOffset = w - MIN((int)strlen(buffer), w); sprintf(bar + (w-strlen(buffer)), "%s", buffer);
snprintf(bar + barOffset, w - barOffset + 1, "%s", buffer);
// First draw in the bar[] buffer... // First draw in the bar[] buffer...
double total = 0.0;
int offset = 0; int offset = 0;
int items = Meter_getItems(this); for (int i = 0; i < type->items; i++) {
for (int i = 0; i < items; i++) {
double value = this->values[i]; double value = this->values[i];
value = MAX(value, 0); value = MAX(value, 0);
value = MIN(value, this->total); value = MIN(value, this->total);
@ -310,12 +284,13 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
} }
} }
offset = nextOffset; offset = nextOffset;
total += this->values[i];
} }
// ...then print the buffer. // ...then print the buffer.
offset = 0; offset = 0;
for (int i = 0; i < items; i++) { for (int i = 0; i < type->items; i++) {
attrset(CRT_colors[Meter_attributes(this)[i]]); attrset(CRT_colors[type->attributes[i]]);
mvaddnstr(y, x + offset, bar + offset, blockSizes[i]); mvaddnstr(y, x + offset, bar + offset, blockSizes[i]);
offset += blockSizes[i]; offset += blockSizes[i];
offset = MAX(offset, 0); offset = MAX(offset, 0);
@ -330,6 +305,8 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
} }
#ifdef USE_FUNKY_MODES
/* ---------- GraphMeterMode ---------- */ /* ---------- GraphMeterMode ---------- */
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0) #define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
@ -344,44 +321,35 @@ static int GraphMeterMode_colors[21] = {
GRAPH_8, GRAPH_8, GRAPH_9 GRAPH_8, GRAPH_8, GRAPH_9
}; };
static const char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_"; static char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_";
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
if (!this->drawData) this->drawData = calloc(1, sizeof(GraphData)); if (!this->drawBuffer) this->drawBuffer = calloc(sizeof(double), METER_BUFFER_LEN);
GraphData* data = (GraphData*) this->drawData; double* drawBuffer = (double*) this->drawBuffer;
const int nValues = METER_BUFFER_LEN;
struct timeval now; for (int i = 0; i < METER_BUFFER_LEN - 1; i++)
gettimeofday(&now, NULL); drawBuffer[i] = drawBuffer[i+1];
if (!timercmp(&now, &(data->time), <)) {
struct timeval delay = { .tv_sec = (int)(DEFAULT_DELAY/10), .tv_usec = (DEFAULT_DELAY-((int)(DEFAULT_DELAY/10)*10)) * 100000 };
timeradd(&now, &delay, &(data->time));
for (int i = 0; i < nValues - 1; i++) MeterType* type = this->type;
data->values[i] = data->values[i+1]; char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
char buffer[nValues];
Meter_setValues(this, buffer, nValues - 1);
double value = 0.0; double value = 0.0;
int items = Meter_getItems(this); for (int i = 0; i < type->items; i++)
for (int i = 0; i < items; i++)
value += this->values[i]; value += this->values[i];
value /= this->total; value /= this->total;
data->values[nValues - 1] = value; drawBuffer[METER_BUFFER_LEN - 1] = value;
} for (int i = METER_BUFFER_LEN - w, k = 0; i < METER_BUFFER_LEN; i++, k++) {
double value = drawBuffer[i];
for (int i = nValues - w, k = 0; i < nValues; i++, k++) {
double value = data->values[i];
DrawDot( CRT_colors[DEFAULT_COLOR], y, ' ' ); DrawDot( CRT_colors[DEFAULT_COLOR], y, ' ' );
DrawDot( CRT_colors[DEFAULT_COLOR], y+1, ' ' ); DrawDot( CRT_colors[DEFAULT_COLOR], y+1, ' ' );
DrawDot( CRT_colors[DEFAULT_COLOR], y+2, ' ' ); DrawDot( CRT_colors[DEFAULT_COLOR], y+2, ' ' );
double threshold = 1.00; double threshold = 1.00;
for (int j = 0; j < 21; j++, threshold -= 0.05) for (int i = 0; i < 21; i++, threshold -= 0.05)
if (value >= threshold) { if (value >= threshold) {
DrawDot(CRT_colors[GraphMeterMode_colors[j]], y+(j/7.0), GraphMeterMode_characters[j]); DrawDot(CRT_colors[GraphMeterMode_colors[i]], y+(i/7.0), GraphMeterMode_characters[i]);
break; break;
} }
} }
@ -390,55 +358,42 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
/* ---------- LEDMeterMode ---------- */ /* ---------- LEDMeterMode ---------- */
static const char* LEDMeterMode_digitsAscii[3][10] = { static char* LEDMeterMode_digits[3][10] = {
{ " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "}, { " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "},
{ "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"}, { "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"},
{ "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"}, { "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"},
}; };
static const char* LEDMeterMode_digitsUtf8[3][10] = {
{ "┌──┐","","╶──┐","╶──┐","╷ ╷","┌──╴","┌──╴","╶──┐","┌──┐","┌──┐"},
{ "│ │","","┌──┘"," ──┤","└──┤","└──┐","├──┐","","├──┤","└──┤"},
{ "└──┘","","└──╴","╶──┘","","╶──┘","└──┘","","└──┘"," ──┘"},
};
static void LEDMeterMode_drawDigit(int x, int y, int n) { static void LEDMeterMode_drawDigit(int x, int y, int n) {
if (CRT_utf8) {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
mvaddstr(y+i, x, LEDMeterMode_digitsUtf8[i][n]); mvaddstr(y+i, x, LEDMeterMode_digits[i][n]);
} else {
for (int i = 0; i < 3; i++)
mvaddstr(y+i, x, LEDMeterMode_digitsAscii[i][n]);
}
} }
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) { static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
(void) w; MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
RichString_begin(out); Meter_displayToStringBuffer(this, buffer);
Meter_displayBuffer(this, buffer, &out);
int yText = CRT_utf8 ? y+1 : y+2;
attrset(CRT_colors[LED_COLOR]); attrset(CRT_colors[LED_COLOR]);
mvaddstr(yText, x, this->caption); mvaddstr(y+2, x, this->caption);
int xx = x + strlen(this->caption); int xx = x + strlen(this->caption);
int len = RichString_sizeVal(out); for (int i = 0; i < Meter_stringBuffer.len; i++) {
for (int i = 0; i < len; i++) { char c = RichString_getCharVal(Meter_stringBuffer, i);
char c = RichString_getCharVal(out, 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;
} else { } else {
mvaddch(yText, xx, c); mvaddch(y+2, xx, c);
xx += 1; xx += 1;
} }
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
RichString_end(out);
} }
#endif
static MeterMode BarMeterMode = { static MeterMode BarMeterMode = {
.uiName = "Bar", .uiName = "Bar",
.h = 1, .h = 1,
@ -451,6 +406,8 @@ static MeterMode TextMeterMode = {
.draw = TextMeterMode_draw, .draw = TextMeterMode_draw,
}; };
#ifdef USE_FUNKY_MODES
static MeterMode GraphMeterMode = { static MeterMode GraphMeterMode = {
.uiName = "Graph", .uiName = "Graph",
.h = 3, .h = 3,
@ -463,41 +420,15 @@ static MeterMode LEDMeterMode = {
.draw = LEDMeterMode_draw, .draw = LEDMeterMode_draw,
}; };
#endif
MeterMode* Meter_modes[] = { MeterMode* Meter_modes[] = {
NULL, NULL,
&BarMeterMode, &BarMeterMode,
&TextMeterMode, &TextMeterMode,
#ifdef USE_FUNKY_MODES
&GraphMeterMode, &GraphMeterMode,
&LEDMeterMode, &LEDMeterMode,
#endif
NULL NULL
}; };
/* Blank meter */
static void BlankMeter_setValues(Meter* this, char* buffer, int size) {
(void) this; (void) buffer; (void) size;
}
static void BlankMeter_display(Object* cast, RichString* out) {
(void) cast;
RichString_prune(out);
}
int BlankMeter_attributes[] = {
DEFAULT_COLOR
};
MeterClass BlankMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = BlankMeter_display,
},
.setValues = BlankMeter_setValues,
.defaultMode = TEXT_METERMODE,
.total = 100.0,
.attributes = BlankMeter_attributes,
.name = "Blank",
.uiName = "Blank",
.caption = ""
};

135
Meter.h
View File

@ -4,91 +4,100 @@
#define HEADER_Meter #define HEADER_Meter
/* /*
htop - Meter.h htop - Meter.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "Object.h"
#include "CRT.h"
#include "ListItem.h"
#include "String.h"
#include "ProcessList.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#ifndef USE_FUNKY_MODES
#define USE_FUNKY_MODES 1
#endif
#define METER_BUFFER_LEN 128 #define METER_BUFFER_LEN 128
#include "ListItem.h"
#include "ProcessList.h"
typedef struct Meter_ Meter; typedef struct Meter_ Meter;
typedef struct MeterType_ MeterType;
typedef struct MeterMode_ MeterMode;
typedef void(*Meter_Init)(Meter*); typedef void(*MeterType_Init)(Meter*);
typedef void(*Meter_Done)(Meter*); typedef void(*MeterType_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int); typedef void(*MeterType_SetMode)(Meter*, int);
typedef void(*Meter_SetValues)(Meter*, char*, int); typedef void(*Meter_SetValues)(Meter*, char*, int);
typedef void(*Meter_Draw)(Meter*, int, int, int); typedef void(*Meter_Draw)(Meter*, int, int, int);
typedef struct MeterClass_ { struct MeterMode_ {
ObjectClass super; Meter_Draw draw;
const Meter_Init init; char* uiName;
const Meter_Done done; int h;
const Meter_UpdateMode updateMode; };
const Meter_Draw draw;
const Meter_SetValues setValues;
const int defaultMode;
const double total;
const int* attributes;
const char* name;
const char* uiName;
const char* caption;
const char maxItems;
char curItems;
} MeterClass;
#define As_Meter(this_) ((MeterClass*)((this_)->super.klass)) struct MeterType_ {
#define Meter_initFn(this_) As_Meter(this_)->init Meter_SetValues setValues;
#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_)) Object_Display display;
#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_)) int mode;
#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode int items;
#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_) double total;
#define Meter_drawFn(this_) As_Meter(this_)->draw int* attributes;
#define Meter_doneFn(this_) As_Meter(this_)->done char* name;
#define Meter_setValues(this_, c_, i_) As_Meter(this_)->setValues((Meter*)(this_), c_, i_) char* uiName;
#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode char* caption;
#define Meter_getItems(this_) As_Meter(this_)->curItems MeterType_Init init;
#define Meter_setItems(this_, n_) As_Meter(this_)->curItems = (n_) MeterType_Done done;
#define Meter_attributes(this_) As_Meter(this_)->attributes MeterType_SetMode setMode;
#define Meter_name(this_) As_Meter(this_)->name Meter_Draw draw;
#define Meter_uiName(this_) As_Meter(this_)->uiName };
struct Meter_ { struct Meter_ {
Object super; Object super;
Meter_Draw draw;
char* caption; char* caption;
MeterType* type;
int mode; int mode;
int param; int param;
void* drawData; Meter_Draw draw;
void* drawBuffer;
int h; int h;
ProcessList* pl; ProcessList* pl;
double* values; double* values;
double total; double total;
}; };
typedef struct MeterMode_ {
Meter_Draw draw;
const char* uiName;
int h;
} MeterMode;
typedef enum { typedef enum {
CUSTOM_METERMODE = 0, CUSTOM_METERMODE = 0,
BAR_METERMODE, BAR_METERMODE,
TEXT_METERMODE, TEXT_METERMODE,
#ifdef USE_FUNKY_MODES
GRAPH_METERMODE, GRAPH_METERMODE,
LED_METERMODE, LED_METERMODE,
#endif
LAST_METERMODE LAST_METERMODE
} MeterModeId; } MeterModeId;
typedef struct GraphData_ {
struct timeval time;
double values[METER_BUFFER_LEN];
} GraphData;
#include "CPUMeter.h"
#include "MemoryMeter.h"
#include "SwapMeter.h"
#include "TasksMeter.h"
#include "LoadAverageMeter.h"
#include "UptimeMeter.h"
#include "ClockMeter.h"
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
@ -97,15 +106,19 @@ typedef struct GraphData_ {
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
extern MeterClass Meter_class; #ifdef DEBUG
extern char* METER_CLASS;
#else
#define METER_CLASS NULL
#endif
extern MeterClass* Meter_types[]; extern MeterType* Meter_types[];
Meter* Meter_new(ProcessList* pl, int param, MeterClass* type); Meter* Meter_new(ProcessList* pl, int param, MeterType* type);
void Meter_delete(Object* cast); void Meter_delete(Object* cast);
void Meter_setCaption(Meter* this, const char* caption); void Meter_setCaption(Meter* this, char* caption);
void Meter_setMode(Meter* this, int modeIndex); void Meter_setMode(Meter* this, int modeIndex);
@ -115,18 +128,20 @@ ListItem* Meter_toListItem(Meter* this);
/* ---------- BarMeterMode ---------- */ /* ---------- BarMeterMode ---------- */
#ifdef USE_FUNKY_MODES
/* ---------- GraphMeterMode ---------- */ /* ---------- GraphMeterMode ---------- */
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0) #define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
/* ---------- LEDMeterMode ---------- */ /* ---------- LEDMeterMode ---------- */
extern MeterMode* Meter_modes[]; #endif
/* Blank meter */ #ifdef USE_FUNKY_MODES
extern int BlankMeter_attributes[]; #endif
extern MeterClass BlankMeter_class; extern MeterMode* Meter_modes[];
#endif #endif

View File

@ -1,20 +1,15 @@
/*
htop - MetersPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "MetersPanel.h" #include "MetersPanel.h"
#include <stdlib.h>
#include <assert.h>
/*{
#include "Panel.h" #include "Panel.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct MetersPanel_ { typedef struct MetersPanel_ {
Panel super; Panel super;
@ -32,7 +27,7 @@ static void MetersPanel_delete(Object* object) {
free(this); free(this);
} }
static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) { static HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
MetersPanel* this = (MetersPanel*) super; MetersPanel* this = (MetersPanel*) super;
int selected = Panel_getSelectedIndex(super); int selected = Panel_getSelectedIndex(super);
@ -84,7 +79,6 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
} }
if (result == HANDLED) { if (result == HANDLED) {
Header* header = this->settings->header; Header* header = this->settings->header;
this->settings->changed = true;
Header_calculateHeight(header); Header_calculateHeight(header);
Header_draw(header); Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
@ -92,22 +86,16 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
return result; return result;
} }
PanelClass MetersPanel_class = { MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr) {
.super = { MetersPanel* this = (MetersPanel*) malloc(sizeof(MetersPanel));
.extends = Class(Panel),
.delete = MetersPanel_delete
},
.eventHandler = MetersPanel_eventHandler
};
MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr) {
MetersPanel* this = AllocThis(MetersPanel);
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true); Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = MetersPanel_delete;
this->settings = settings; this->settings = settings;
this->meters = meters; this->meters = meters;
this->scr = scr; this->scr = scr;
super->eventHandler = MetersPanel_EventHandler;
Panel_setHeader(super, header); Panel_setHeader(super, header);
for (int i = 0; i < Vector_size(meters); i++) { for (int i = 0; i < Vector_size(meters); i++) {
Meter* meter = (Meter*) Vector_get(meters, i); Meter* meter = (Meter*) Vector_get(meters, i);

View File

@ -2,17 +2,16 @@
#ifndef HEADER_MetersPanel #ifndef HEADER_MetersPanel
#define HEADER_MetersPanel #define HEADER_MetersPanel
/*
htop - MetersPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h" #include "Panel.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct MetersPanel_ { typedef struct MetersPanel_ {
Panel super; Panel super;
@ -22,8 +21,6 @@ typedef struct MetersPanel_ {
} MetersPanel; } MetersPanel;
extern PanelClass MetersPanel_class; MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr);
MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr);
#endif #endif

4
NEWS
View File

@ -1,5 +1,5 @@
See the commit history for news of the past. See the ChangeLog for news of the past.
See the bug tracker for news of the future. See the TODO list for news of the future.
Run the program for news of the present. Run the program for news of the present.

View File

@ -1,14 +1,24 @@
/* /*
htop - Object.c htop
(C) 2004-2012 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h" #include "Object.h"
#include "RichString.h"
#include "CRT.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "debug.h"
/*{ /*{
#include "RichString.h"
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
typedef struct Object_ Object; typedef struct Object_ Object;
@ -16,47 +26,32 @@ typedef void(*Object_Display)(Object*, RichString*);
typedef int(*Object_Compare)(const void*, const void*); typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*); typedef void(*Object_Delete)(Object*);
#define Object_getClass(obj_) ((Object*)(obj_))->klass
#define Object_setClass(obj_, class_) Object_getClass(obj_) = (ObjectClass*) class_
#define Object_delete(obj_) Object_getClass(obj_)->delete((Object*)(obj_))
#define Object_displayFn(obj_) Object_getClass(obj_)->display
#define Object_display(obj_, str_) Object_getClass(obj_)->display((Object*)(obj_), str_)
#define Object_compare(obj_, other_) Object_getClass(obj_)->compare((const void*)(obj_), other_)
#define Class(class_) ((ObjectClass*)(&(class_ ## _class)))
#define AllocThis(class_) (class_*) malloc(sizeof(class_)); Object_setClass(this, Class(class_));
typedef struct ObjectClass_ {
const void* extends;
const Object_Display display;
const Object_Delete delete;
const Object_Compare compare;
} ObjectClass;
struct Object_ { struct Object_ {
ObjectClass* klass; #ifdef DEBUG
char* class;
#endif
Object_Display display;
Object_Delete delete;
}; };
}*/ }*/
ObjectClass Object_class = { #ifdef DEBUG
.extends = NULL char* OBJECT_CLASS = "Object";
};
#else
#define OBJECT_CLASS NULL
#endif
#ifdef DEBUG #ifdef DEBUG
bool Object_isA(Object* o, const ObjectClass* klass) { void Object_setClass(void* this, char* class) {
if (!o) ((Object*)this)->class = class;
return false;
const ObjectClass* type = o->klass;
while (type) {
if (type == klass)
return true;
type = type->extends;
} }
return false;
static void Object_display(Object* this, RichString* out) {
char objAddress[50];
sprintf(objAddress, "%s @ %p", this->class, (void*) this);
RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress);
} }
#endif #endif

View File

@ -3,13 +3,24 @@
#ifndef HEADER_Object #ifndef HEADER_Object
#define HEADER_Object #define HEADER_Object
/* /*
htop - Object.h htop
(C) 2004-2012 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "RichString.h" #include "RichString.h"
#include "CRT.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "debug.h"
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
typedef struct Object_ Object; typedef struct Object_ Object;
@ -17,35 +28,24 @@ typedef void(*Object_Display)(Object*, RichString*);
typedef int(*Object_Compare)(const void*, const void*); typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*); typedef void(*Object_Delete)(Object*);
#define Object_getClass(obj_) ((Object*)(obj_))->klass
#define Object_setClass(obj_, class_) Object_getClass(obj_) = (ObjectClass*) class_
#define Object_delete(obj_) Object_getClass(obj_)->delete((Object*)(obj_))
#define Object_displayFn(obj_) Object_getClass(obj_)->display
#define Object_display(obj_, str_) Object_getClass(obj_)->display((Object*)(obj_), str_)
#define Object_compare(obj_, other_) Object_getClass(obj_)->compare((const void*)(obj_), other_)
#define Class(class_) ((ObjectClass*)(&(class_ ## _class)))
#define AllocThis(class_) (class_*) malloc(sizeof(class_)); Object_setClass(this, Class(class_));
typedef struct ObjectClass_ {
const void* extends;
const Object_Display display;
const Object_Delete delete;
const Object_Compare compare;
} ObjectClass;
struct Object_ { struct Object_ {
ObjectClass* klass; #ifdef DEBUG
char* class;
#endif
Object_Display display;
Object_Delete delete;
}; };
#ifdef DEBUG
extern char* OBJECT_CLASS;
extern ObjectClass Object_class; #else
#define OBJECT_CLASS NULL
#endif
#ifdef DEBUG #ifdef DEBUG
bool Object_isA(Object* o, const ObjectClass* klass); void Object_setClass(void* this, char* class);
#endif #endif

View File

@ -1,246 +0,0 @@
/*
htop - OpenFilesScreen.c
(C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "OpenFilesScreen.h"
#include "CRT.h"
#include "ProcessList.h"
#include "ListItem.h"
#include "IncSet.h"
#include "String.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
/*{
#include "Process.h"
#include "Panel.h"
#include "FunctionBar.h"
typedef struct OpenFiles_Data_ {
char* data[256];
} OpenFiles_Data;
typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ {
Process* process;
pid_t pid;
Panel* display;
FunctionBar* bar;
} OpenFilesScreen;
}*/
static const char* ofsFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL};
static const char* ofsKeys[] = {"F3", "F4", "F5", "Esc"};
static int ofsEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
OpenFilesScreen* OpenFilesScreen_new(Process* process) {
OpenFilesScreen* this = (OpenFilesScreen*) malloc(sizeof(OpenFilesScreen));
this->process = process;
this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem));
if (Process_isThread(process))
this->pid = process->tgid;
else
this->pid = process->pid;
return this;
}
void OpenFilesScreen_delete(OpenFilesScreen* this) {
Panel_delete((Object*)this->display);
free(this);
}
static void OpenFilesScreen_draw(OpenFilesScreen* this, IncSet* inc) {
attrset(CRT_colors[METER_TEXT]);
mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Snapshot of files open in process %d - %s", this->pid, this->process->comm);
attrset(CRT_colors[DEFAULT_COLOR]);
Panel_draw(this->display, true);
IncSet_drawBar(inc);
}
static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
char command[1025];
snprintf(command, 1024, "lsof -P -p %d -F 2> /dev/null", pid);
FILE* fd = popen(command, "r");
OpenFiles_ProcessData* pdata = calloc(1, sizeof(OpenFiles_ProcessData));
OpenFiles_FileData* fdata = NULL;
OpenFiles_Data* item = &(pdata->data);
if (!fd) {
pdata->error = 127;
return pdata;
}
while (!feof(fd)) {
int cmd = fgetc(fd);
if (cmd == EOF)
break;
char* entry = malloc(1024);
if (!fgets(entry, 1024, fd)) {
free(entry);
break;
}
char* newline = strrchr(entry, '\n');
*newline = '\0';
if (cmd == 'f') {
OpenFiles_FileData* nextFile = calloc(1, sizeof(OpenFiles_FileData));
if (fdata == NULL) {
pdata->files = nextFile;
} else {
fdata->next = nextFile;
}
fdata = nextFile;
item = &(fdata->data);
}
assert(cmd >= 0 && cmd <= 0xff);
item->data[cmd] = entry;
}
pdata->error = pclose(fd);
return pdata;
}
static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) {
Vector_add(lines, (Object*) ListItem_new(line, 0));
if (!incFilter || String_contains_i(line, incFilter))
Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1));
}
static inline void OpenFiles_Data_clear(OpenFiles_Data* data) {
for (int i = 0; i < 255; i++)
if (data->data[i])
free(data->data[i]);
}
static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* inc) {
Panel* panel = this->display;
int idx = Panel_getSelectedIndex(panel);
Panel_prune(panel);
OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(this->pid);
if (pdata->error == 127) {
addLine("Could not execute 'lsof'. Please make sure it is available in your $PATH.", lines, panel, IncSet_filter(inc));
} else if (pdata->error == 1) {
addLine("Failed listing open files.", lines, panel, IncSet_filter(inc));
} else {
OpenFiles_FileData* fdata = pdata->files;
while (fdata) {
char entry[1024];
char** data = fdata->data.data;
sprintf(entry, "%5s %4s %10s %10s %10s %s",
data['f'] ? data['f'] : "",
data['t'] ? data['t'] : "",
data['D'] ? data['D'] : "",
data['s'] ? data['s'] : "",
data['i'] ? data['i'] : "",
data['n'] ? data['n'] : "");
addLine(entry, lines, panel, IncSet_filter(inc));
OpenFiles_Data_clear(&fdata->data);
OpenFiles_FileData* old = fdata;
fdata = fdata->next;
free(old);
}
OpenFiles_Data_clear(&pdata->data);
}
free(pdata);
Vector_insertionSort(lines);
Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx);
}
void OpenFilesScreen_run(OpenFilesScreen* this) {
Panel* panel = this->display;
Panel_setHeader(panel, " FD TYPE DEVICE SIZE NODE NAME");
FunctionBar* bar = FunctionBar_new(ofsFunctions, ofsKeys, ofsEvents);
IncSet* inc = IncSet_new(bar);
Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE);
OpenFilesScreen_scan(this, lines, inc);
OpenFilesScreen_draw(this, inc);
bool looping = true;
while (looping) {
Panel_draw(panel, true);
if (inc->active)
move(LINES-1, CRT_cursorX);
int ch = getch();
if (ch == KEY_MOUSE) {
MEVENT mevent;
int ok = getmouse(&mevent);
if (ok == OK)
if (mevent.y >= panel->y && mevent.y < LINES - 1) {
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
ch = 0;
} if (mevent.y == LINES - 1)
ch = FunctionBar_synthesizeEvent(inc->bar, mevent.x);
}
if (inc->active) {
IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines);
continue;
}
switch(ch) {
case ERR:
continue;
case KEY_F(3):
case '/':
IncSet_activate(inc, INC_SEARCH);
break;
case KEY_F(4):
case '\\':
IncSet_activate(inc, INC_FILTER);
break;
case KEY_F(5):
clear();
OpenFilesScreen_scan(this, lines, inc);
OpenFilesScreen_draw(this, inc);
break;
case '\014': // Ctrl+L
clear();
OpenFilesScreen_draw(this, inc);
break;
case 'q':
case 27:
case KEY_F(10):
looping = false;
break;
case KEY_RESIZE:
Panel_resize(panel, COLS, LINES-2);
OpenFilesScreen_draw(this, inc);
break;
default:
Panel_onKey(panel, ch);
}
}
Vector_delete(lines);
FunctionBar_delete((Object*)bar);
IncSet_delete(inc);
}

View File

@ -1,45 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_OpenFilesScreen
#define HEADER_OpenFilesScreen
/*
htop - OpenFilesScreen.h
(C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Process.h"
#include "Panel.h"
#include "FunctionBar.h"
typedef struct OpenFiles_Data_ {
char* data[256];
} OpenFiles_Data;
typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ {
Process* process;
pid_t pid;
Panel* display;
FunctionBar* bar;
} OpenFilesScreen;
OpenFilesScreen* OpenFilesScreen_new(Process* process);
void OpenFilesScreen_delete(OpenFilesScreen* this);
void OpenFilesScreen_run(OpenFilesScreen* this);
#endif

263
Panel.c
View File

@ -1,29 +1,27 @@
/* /*
htop - Panel.c htop - Panel.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h"
#include "Panel.h" #include "Panel.h"
#include "Vector.h"
#include "CRT.h" #include "CRT.h"
#include "RichString.h" #include "RichString.h"
#include "ListItem.h" #include "ListItem.h"
#include "String.h"
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include <ctype.h> #include "debug.h"
#include <string.h>
#include <assert.h> #include <assert.h>
#include <curses.h>
//#link curses //#link curses
/*{ /*{
#include "Object.h"
#include "Vector.h"
typedef struct Panel_ Panel; typedef struct Panel_ Panel;
@ -37,28 +35,18 @@ typedef enum HandlerResult_ {
typedef HandlerResult(*Panel_EventHandler)(Panel*, int); typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
typedef struct PanelClass_ {
const ObjectClass super;
const Panel_EventHandler eventHandler;
} PanelClass;
#define As_Panel(this_) ((PanelClass*)((this_)->super.klass))
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
#define Panel_eventHandler(this_, ev_) As_Panel(this_)->eventHandler((Panel*)(this_), ev_)
struct Panel_ { struct Panel_ {
Object super; Object super;
PanelClass* class;
int x, y, w, h; int x, y, w, h;
WINDOW* window; WINDOW* window;
Vector* items; Vector* items;
int selected; int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected; int oldSelected;
char* eventHandlerBuffer;
int scrollV;
short scrollH;
bool needsRedraw; bool needsRedraw;
RichString header; RichString header;
Panel_EventHandler eventHandler;
}; };
}*/ }*/
@ -70,24 +58,18 @@ struct Panel_ {
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#define KEY_CTRLN 0016 /* control-n key */ #ifdef DEBUG
#define KEY_CTRLP 0020 /* control-p key */ char* PANEL_CLASS = "Panel";
#define KEY_CTRLF 0006 /* control-f key */ #else
#define KEY_CTRLB 0002 /* control-b key */ #define PANEL_CLASS NULL
#endif
PanelClass Panel_class = {
.super = {
.extends = Class(Object),
.delete = Panel_delete
},
.eventHandler = Panel_selectByTyping
};
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type) { Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
Panel* this; Panel* this;
this = malloc(sizeof(Panel)); this = malloc(sizeof(Panel));
Object_setClass(this, Class(Panel));
Panel_init(this, x, y, w, h, type, owner); Panel_init(this, x, y, w, h, type, owner);
this->items->compare = compare;
return this; return this;
} }
@ -97,38 +79,46 @@ void Panel_delete(Object* cast) {
free(this); free(this);
} }
void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool owner) { void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
Object* super = (Object*) this;
Object_setClass(this, PANEL_CLASS);
super->delete = Panel_delete;
this->x = x; this->x = x;
this->y = y; this->y = y;
this->w = w; this->w = w;
this->h = h; this->h = h;
this->eventHandlerBuffer = NULL; this->eventHandler = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE); this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
this->scrollV = 0; this->scrollV = 0;
this->scrollH = 0; this->scrollH = 0;
this->selected = 0; this->selected = 0;
this->oldSelected = 0; this->oldSelected = 0;
this->needsRedraw = true; this->needsRedraw = true;
RichString_beginAllocated(this->header); this->header.len = 0;
if (String_eq(CRT_termType, "linux"))
this->scrollHAmount = 40;
else
this->scrollHAmount = 5;
} }
void Panel_done(Panel* this) { void Panel_done(Panel* this) {
assert (this != NULL); assert (this != NULL);
free(this->eventHandlerBuffer);
Vector_delete(this->items); Vector_delete(this->items);
RichString_end(this->header);
} }
RichString* Panel_getHeader(Panel* this) { inline void Panel_setRichHeader(Panel* this, RichString header) {
assert (this != NULL); assert (this != NULL);
this->header = header;
this->needsRedraw = true; this->needsRedraw = true;
return &(this->header);
} }
inline void Panel_setHeader(Panel* this, const char* header) { inline void Panel_setHeader(Panel* this, char* header) {
RichString_write(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header); Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
this->needsRedraw = true; }
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
this->eventHandler = eh;
} }
void Panel_move(Panel* this, int x, int y) { void Panel_move(Panel* this, int x, int y) {
@ -142,7 +132,7 @@ void Panel_move(Panel* this, int x, int y) {
void Panel_resize(Panel* this, int w, int h) { void Panel_resize(Panel* this, int w, int h) {
assert (this != NULL); assert (this != NULL);
if (RichString_sizeVal(this->header) > 0) if (this->header.len > 0)
h--; h--;
this->w = w; this->w = w;
this->h = h; this->h = h;
@ -197,10 +187,8 @@ Object* Panel_remove(Panel* this, int i) {
Object* Panel_getSelected(Panel* this) { Object* Panel_getSelected(Panel* this) {
assert (this != NULL); assert (this != NULL);
if (Vector_size(this->items) > 0)
return Vector_get(this->items, this->selected); return Vector_get(this->items, this->selected);
else
return NULL;
} }
void Panel_moveSelectedUp(Panel* this) { void Panel_moveSelectedUp(Panel* this) {
@ -225,7 +213,7 @@ int Panel_getSelectedIndex(Panel* this) {
return this->selected; return this->selected;
} }
int Panel_size(Panel* this) { int Panel_getSize(Panel* this) {
assert (this != NULL); assert (this != NULL);
return Vector_size(this->items); return Vector_size(this->items);
@ -236,23 +224,26 @@ void Panel_setSelected(Panel* this, int selected) {
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected)); selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
this->selected = selected; this->selected = selected;
if (Panel_eventHandlerFn(this)) { if (this->eventHandler) {
Panel_eventHandler(this, EVENT_SETSELECTED); this->eventHandler(this, EVENT_SETSELECTED);
} }
} }
void Panel_draw(Panel* this, bool focus) { void Panel_draw(Panel* this, bool focus) {
assert (this != NULL); assert (this != NULL);
int first, last;
int itemCount = Vector_size(this->items); int itemCount = Vector_size(this->items);
int scrollH = this->scrollH; int scrollH = this->scrollH;
int y = this->y; int x = this->x; int y = this->y; int x = this->x;
int first = this->scrollV; first = this->scrollV;
if (itemCount > this->h && first > itemCount - this->h) {
first = itemCount - this->h; if (this->h > itemCount) {
this->scrollV = first; last = this->scrollV + itemCount;
move(y + last, x + 0);
} else {
last = MIN(itemCount, this->scrollV + this->h);
} }
int last = MIN(itemCount, first + MIN(itemCount, this->h));
if (this->selected < first) { if (this->selected < first) {
first = this->selected; first = this->selected;
this->scrollV = first; this->scrollV = first;
@ -267,16 +258,15 @@ void Panel_draw(Panel* this, bool focus) {
assert(first >= 0); assert(first >= 0);
assert(last <= itemCount); assert(last <= itemCount);
int headerLen = RichString_sizeVal(this->header); if (this->header.len > 0) {
if (headerLen > 0) {
int attr = focus int attr = focus
? CRT_colors[PANEL_HEADER_FOCUS] ? CRT_colors[PANEL_HEADER_FOCUS]
: CRT_colors[PANEL_HEADER_UNFOCUS]; : CRT_colors[PANEL_HEADER_UNFOCUS];
attrset(attr); attrset(attr);
mvhline(y, x, ' ', this->w); mvhline(y, x, ' ', this->w);
if (scrollH < headerLen) { if (scrollH < this->header.len) {
RichString_printoffnVal(this->header, y, x, scrollH, RichString_printoffnVal(this->header, y, x, scrollH,
MIN(headerLen - scrollH, this->w)); MIN(this->header.len - scrollH, this->w));
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
y++; y++;
@ -290,22 +280,22 @@ void Panel_draw(Panel* this, bool focus) {
for(int i = first, j = 0; j < this->h && i < last; i++, j++) { for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
Object* itemObj = Vector_get(this->items, i); Object* itemObj = Vector_get(this->items, i);
assert(itemObj); if(!itemObj) continue; RichString itemRef;
RichString_begin(item); RichString_initVal(itemRef);
Object_display(itemObj, &item); itemObj->display(itemObj, &itemRef);
int itemLen = RichString_sizeVal(item); int amt = MIN(itemRef.len - scrollH, this->w);
int amt = MIN(itemLen - scrollH, this->w); if (i == this->selected) {
bool selected = (i == this->selected);
if (selected) {
attrset(highlight); attrset(highlight);
RichString_setAttr(&item, highlight); RichString_setAttr(&itemRef, highlight);
} mvhline(y + j, x+0, ' ', this->w);
mvhline(y + j, x, ' ', this->w);
if (amt > 0) if (amt > 0)
RichString_printoffnVal(item, y+j, x, scrollH, amt); RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
if (selected)
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
RichString_end(item); } else {
mvhline(y+j, x+0, ' ', this->w);
if (amt > 0)
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++)
mvhline(i, x+0, ' ', this->w); mvhline(i, x+0, ' ', this->w);
@ -313,139 +303,66 @@ void Panel_draw(Panel* this, bool focus) {
} else { } else {
Object* oldObj = Vector_get(this->items, this->oldSelected); Object* oldObj = Vector_get(this->items, this->oldSelected);
assert(oldObj); RichString oldRef;
RichString_begin(old); RichString_initVal(oldRef);
Object_display(oldObj, &old); oldObj->display(oldObj, &oldRef);
int oldLen = RichString_sizeVal(old);
Object* newObj = Vector_get(this->items, this->selected); Object* newObj = Vector_get(this->items, this->selected);
RichString_begin(new); RichString newRef;
Object_display(newObj, &new); RichString_initVal(newRef);
int newLen = RichString_sizeVal(new); 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 < oldLen) if (scrollH < oldRef.len)
RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x, RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
scrollH, MIN(oldLen - scrollH, this->w)); 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(&new, highlight); RichString_setAttr(&newRef, highlight);
if (scrollH < newLen) if (scrollH < newRef.len)
RichString_printoffnVal(new, y+this->selected - this->scrollV, x, RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
scrollH, MIN(newLen - scrollH, this->w)); this->scrollH, MIN(newRef.len - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
RichString_end(new);
RichString_end(old);
} }
this->oldSelected = this->selected; this->oldSelected = this->selected;
move(0, 0); move(0, 0);
} }
bool Panel_onKey(Panel* this, int key) { void Panel_onKey(Panel* this, int key) {
assert (this != NULL); assert (this != NULL);
switch (key) { switch (key) {
case KEY_DOWN: case KEY_DOWN:
case KEY_CTRLN:
if (this->selected + 1 < Vector_size(this->items)) if (this->selected + 1 < Vector_size(this->items))
this->selected++; this->selected++;
return true; break;
case KEY_UP: case KEY_UP:
case KEY_CTRLP:
if (this->selected > 0) if (this->selected > 0)
this->selected--; this->selected--;
return true; break;
#ifdef KEY_C_DOWN
case KEY_C_DOWN:
if (this->selected + 1 < Vector_size(this->items)) {
this->selected++;
if (this->scrollV < Vector_size(this->items) - this->h) {
this->scrollV++;
this->needsRedraw = true;
}
}
return true;
#endif
#ifdef KEY_C_UP
case KEY_C_UP:
if (this->selected > 0) {
this->selected--;
if (this->scrollV > 0) {
this->scrollV--;
this->needsRedraw = true;
}
}
return true;
#endif
case KEY_LEFT: case KEY_LEFT:
case KEY_CTRLB:
if (this->scrollH > 0) { if (this->scrollH > 0) {
this->scrollH -= CRT_scrollHAmount; this->scrollH -= this->scrollHAmount;
this->needsRedraw = true; this->needsRedraw = true;
} }
return true; break;
case KEY_RIGHT: case KEY_RIGHT:
case KEY_CTRLF: this->scrollH += this->scrollHAmount;
this->scrollH += CRT_scrollHAmount;
this->needsRedraw = true; this->needsRedraw = true;
return true; break;
case KEY_PPAGE: case KEY_PPAGE:
this->selected -= (this->h - 1); this->selected -= this->h;
this->scrollV -= (this->h - 1);
if (this->selected < 0) if (this->selected < 0)
this->selected = 0; this->selected = 0;
if (this->scrollV < 0) break;
this->scrollV = 0;
this->needsRedraw = true;
return true;
case KEY_NPAGE: case KEY_NPAGE:
this->selected += (this->h - 1); this->selected += this->h;
int size = Vector_size(this->items); int size = Vector_size(this->items);
if (this->selected >= size) if (this->selected >= size)
this->selected = size - 1; this->selected = size - 1;
this->scrollV += (this->h - 1); break;
if (this->scrollV >= MAX(0, size - this->h))
this->scrollV = MAX(0, size - this->h - 1);
this->needsRedraw = true;
return true;
case KEY_HOME: case KEY_HOME:
this->selected = 0; this->selected = 0;
return true; break;
case KEY_END: case KEY_END:
this->selected = Vector_size(this->items) - 1; this->selected = Vector_size(this->items) - 1;
return true; break;
}
return false;
}
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
int size = Panel_size(this);
if (!this->eventHandlerBuffer)
this->eventHandlerBuffer = calloc(100, 1);
if (isalnum(ch)) {
int len = strlen(this->eventHandlerBuffer);
if (len < 99) {
this->eventHandlerBuffer[len] = ch;
this->eventHandlerBuffer[len+1] = '\0';
}
for (int try = 0; try < 2; try++) {
len = strlen(this->eventHandlerBuffer);
for (int i = 0; i < size; i++) {
char* cur = ((ListItem*) Panel_get(this, i))->value;
while (*cur == ' ') cur++;
if (strncasecmp(cur, this->eventHandlerBuffer, len) == 0) {
Panel_setSelected(this, i);
return HANDLED;
} }
} }
this->eventHandlerBuffer[0] = ch;
this->eventHandlerBuffer[1] = '\0';
}
return HANDLED;
} else if (ch != ERR) {
this->eventHandlerBuffer[0] = '\0';
}
if (ch == 13) {
return BREAK_LOOP;
}
return IGNORED;
}

59
Panel.h
View File

@ -4,15 +4,26 @@
#define HEADER_Panel #define HEADER_Panel
/* /*
htop - Panel.h htop - Panel.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
//#link curses
#include "Object.h" #include "Object.h"
#include "Vector.h" #include "Vector.h"
#include "CRT.h"
#include "RichString.h"
#include "ListItem.h"
#include <math.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
typedef struct Panel_ Panel; typedef struct Panel_ Panel;
@ -26,28 +37,18 @@ typedef enum HandlerResult_ {
typedef HandlerResult(*Panel_EventHandler)(Panel*, int); typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
typedef struct PanelClass_ {
const ObjectClass super;
const Panel_EventHandler eventHandler;
} PanelClass;
#define As_Panel(this_) ((PanelClass*)((this_)->super.klass))
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
#define Panel_eventHandler(this_, ev_) As_Panel(this_)->eventHandler((Panel*)(this_), ev_)
struct Panel_ { struct Panel_ {
Object super; Object super;
PanelClass* class;
int x, y, w, h; int x, y, w, h;
WINDOW* window; WINDOW* window;
Vector* items; Vector* items;
int selected; int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected; int oldSelected;
char* eventHandlerBuffer;
int scrollV;
short scrollH;
bool needsRedraw; bool needsRedraw;
RichString header; RichString header;
Panel_EventHandler eventHandler;
}; };
@ -58,24 +59,26 @@ struct Panel_ {
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#define KEY_CTRLN 0016 /* control-n key */ #ifdef DEBUG
#define KEY_CTRLP 0020 /* control-p key */ extern char* PANEL_CLASS;
#define KEY_CTRLF 0006 /* control-f key */ #else
#define KEY_CTRLB 0002 /* control-b key */ #define PANEL_CLASS NULL
#endif
extern PanelClass Panel_class;
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type); Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare);
void Panel_delete(Object* cast); void Panel_delete(Object* cast);
void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool owner); void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner);
void Panel_done(Panel* this); void Panel_done(Panel* this);
RichString* Panel_getHeader(Panel* this); extern void Panel_setRichHeader(Panel* this, RichString header);
extern void Panel_setHeader(Panel* this, const char* header); extern void Panel_setHeader(Panel* this, char* header);
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh);
void Panel_move(Panel* this, int x, int y); void Panel_move(Panel* this, int x, int y);
@ -101,14 +104,12 @@ void Panel_moveSelectedDown(Panel* this);
int Panel_getSelectedIndex(Panel* this); int Panel_getSelectedIndex(Panel* this);
int Panel_size(Panel* this); int Panel_getSize(Panel* this);
void Panel_setSelected(Panel* this, int selected); void Panel_setSelected(Panel* this, int selected);
void Panel_draw(Panel* this, bool focus); void Panel_draw(Panel* this, bool focus);
bool Panel_onKey(Panel* this, int key); void Panel_onKey(Panel* this, int key);
HandlerResult Panel_selectByTyping(Panel* this, int ch);
#endif #endif

698
Process.c
View File

@ -1,67 +1,44 @@
/* /*
htop - Process.c htop - Process.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Process.h" #define _GNU_SOURCE
#include "ProcessList.h" #include "ProcessList.h"
#include "Object.h"
#include "CRT.h" #include "CRT.h"
#include "String.h" #include "String.h"
#include "Process.h"
#include "RichString.h" #include "RichString.h"
#include "debug.h"
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <pwd.h> #include <pwd.h>
#include <sched.h> #include <sched.h>
#include <time.h>
#include <assert.h>
#include <sys/syscall.h>
#ifdef HAVE_LIBHWLOC #include <plpa.h>
#include <hwloc/linux.h>
#endif
// This works only with glibc 2.1+. On earlier versions // This works only with glibc 2.1+. On earlier versions
// the behavior is similar to have a hardcoded page size. // the behavior is similar to have a hardcoded page size.
#ifndef PAGE_SIZE #ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) ) #define PAGE_SIZE ( sysconf(_SC_PAGESIZE) / 1024 )
#endif #endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
#define PROCESS_COMM_LEN 300
/*{ /*{
#include "Object.h"
#include "Affinity.h"
#include "IOPriority.h"
#include <sys/types.h>
#define PROCESS_FLAG_IO 1
#define PROCESS_FLAG_IOPRIO 2
#define PROCESS_FLAG_OPENVZ 4
#define PROCESS_FLAG_VSERVER 8
#define PROCESS_FLAG_CGROUP 16
#ifndef Process_isKernelThread
#define Process_isKernelThread(_process) (_process->pgrp == 0)
#endif
#ifndef Process_isUserlandThread
#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
#endif
#ifndef Process_isThread
#define Process_isThread(_process) (Process_isUserlandThread(_process) || Process_isKernelThread(_process))
#endif
typedef enum ProcessField_ { typedef enum ProcessField_ {
PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME, PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME,
@ -70,21 +47,11 @@ typedef enum ProcessField_ {
PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM, PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
USER, TIME, NLWP, TGID, USER, TIME, NLWP, TGID,
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
CTID, VPID, VEID, VPID,
#endif
#ifdef HAVE_VSERVER
VXID,
#endif #endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE, RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE,
#endif #endif
#ifdef HAVE_CGROUP
CGROUP,
#endif
#ifdef HAVE_OOM
OOM,
#endif
IO_PRIORITY,
LAST_PROCESSFIELD LAST_PROCESSFIELD
} ProcessField; } ProcessField;
@ -94,86 +61,36 @@ typedef struct Process_ {
Object super; Object super;
struct ProcessList_ *pl; struct ProcessList_ *pl;
bool updated;
pid_t pid; unsigned int pid;
char* comm; char* comm;
int indent; int indent;
char state; char state;
bool tag; bool tag;
bool showChildren; unsigned int ppid;
bool show;
pid_t ppid;
unsigned int pgrp; unsigned int pgrp;
unsigned int session; unsigned int session;
unsigned int tty_nr; unsigned int tty_nr;
pid_t tgid; unsigned int tgid;
int tpgid; int tpgid;
unsigned long int flags; unsigned long int flags;
#ifdef DEBUG
uid_t st_uid;
float percent_cpu;
float percent_mem;
char* user;
unsigned long long int utime;
unsigned long long int stime;
unsigned long long int cutime;
unsigned long long int cstime;
long int priority;
long int nice;
long int nlwp;
IOPriority ioPriority;
char starttime_show[8];
time_t starttime_ctime;
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
int processor;
long m_size;
long m_resident;
long m_share;
long m_trs;
long m_drs;
long m_lrs;
long m_dt;
#ifdef HAVE_OPENVZ
unsigned int ctid;
unsigned int vpid;
#endif
#ifdef HAVE_VSERVER
unsigned int vxid;
#endif
#ifdef HAVE_CGROUP
char* cgroup;
#endif
#ifdef HAVE_OOM
unsigned int oom;
#endif
int exit_signal;
int basenameOffset;
bool updated;
unsigned long int minflt; unsigned long int minflt;
unsigned long int cminflt; unsigned long int cminflt;
unsigned long int majflt; unsigned long int majflt;
unsigned long int cmajflt; unsigned long int cmajflt;
#endif
unsigned long int utime;
unsigned long int stime;
long int cutime;
long int cstime;
long int priority;
long int nice;
long int nlwp;
#ifdef DEBUG #ifdef DEBUG
long int itrealvalue; long int itrealvalue;
unsigned long int starttime;
unsigned long int vsize; unsigned long int vsize;
long int rss; long int rss;
unsigned long int rlim; unsigned long int rlim;
@ -190,12 +107,47 @@ typedef struct Process_ {
unsigned long int nswap; unsigned long int nswap;
unsigned long int cnswap; unsigned long int cnswap;
#endif #endif
int exit_signal;
int processor;
int m_size;
int m_resident;
int m_share;
int m_trs;
int m_drs;
int m_lrs;
int m_dt;
uid_t st_uid;
float percent_cpu;
float percent_mem;
char* user;
#ifdef HAVE_OPENVZ
unsigned int veid;
unsigned int vpid;
#endif
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
} Process; } Process;
}*/ }*/
const char *Process_fieldNames[] = { #ifdef DEBUG
char* PROCESS_CLASS = "Process";
#else
#define PROCESS_CLASS NULL
#endif
char *Process_fieldNames[] = {
"", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION", "", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION",
"TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT", "TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT",
"UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE", "UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE",
@ -205,223 +157,79 @@ const char *Process_fieldNames[] = {
"M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM", "M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM",
"USER", "TIME", "NLWP", "TGID", "USER", "TIME", "NLWP", "TGID",
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
"CTID", "VPID", "VEID", "VPID",
#endif
#ifdef HAVE_VSERVER
"VXID",
#endif #endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
"RCHAR", "WCHAR", "SYSCR", "SYSCW", "RBYTES", "WBYTES", "CNCLWB", "RCHAR", "WCHAR", "SYSCR", "SYSCW", "RBYTES", "WBYTES", "CNCLWB",
"IO_READ_RATE", "IO_WRITE_RATE", "IO_RATE", "IO_READ_RATE", "IO_WRITE_RATE", "IO_RATE",
#endif #endif
#ifdef HAVE_CGROUP
"CGROUP",
#endif
#ifdef HAVE_OOM
"OOM",
#endif
"IO_PRIORITY",
"*** report bug! ***" "*** report bug! ***"
}; };
const int Process_fieldFlags[] = { char *Process_fieldTitles[] = {
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
#ifdef HAVE_OPENVZ
PROCESS_FLAG_OPENVZ, PROCESS_FLAG_OPENVZ,
#endif
#ifdef HAVE_VSERVER
PROCESS_FLAG_VSERVER,
#endif
#ifdef HAVE_TASKSTATS
PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO,
PROCESS_FLAG_IO, PROCESS_FLAG_IO, PROCESS_FLAG_IO,
#endif
#ifdef HAVE_CGROUP
PROCESS_FLAG_CGROUP,
#endif
#ifdef HAVE_OOM
0,
#endif
PROCESS_FLAG_IOPRIO
};
const char *Process_fieldTitles[] = {
"", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ", "", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ",
" TTY ", " TPGID ", "- ", " MINFLT ", " CMINFLT ", " MAJFLT ", " CMAJFLT ", " TTY ", "TPGID ", "- ", "- ", "- ", "- ", "- ",
" UTIME+ ", " STIME+ ", " CUTIME+ ", " CSTIME+ ", "PRI ", " NI ", "- ", " UTIME+ ", " STIME+ ", "- ", "- ", "PRI ", " NI ", "- ",
"START ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ",
"- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ",
"- ", "- ", "- ", "CPU ", " VIRT ", " RES ", " SHR ", "- ", "- ", "- ", "CPU ", " VIRT ", " RES ", " SHR ",
" CODE ", " DATA ", " LIB ", " DIRTY ", " UID ", "CPU% ", "MEM% ", " CODE ", " DATA ", " LIB ", " DIRTY ", " UID ", "CPU% ", "MEM% ",
"USER ", " TIME+ ", "NLWP ", " TGID ", "USER ", " TIME+ ", "NLWP ", " TGID ",
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
" CTID ", " VPID ", " VEID ", " VPID ",
#endif
#ifdef HAVE_VSERVER
" VXID ",
#endif #endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
" RD_CHAR ", " WR_CHAR ", " RD_SYSC ", " WR_SYSC ", " IO_RBYTES ", " IO_WBYTES ", " IO_CANCEL ", " RD_CHAR ", " WR_CHAR ", " RD_SYSC ", " WR_SYSC ", " IO_RD ", " IO_WR ", " IO_CANCEL ",
" IORR ", " IOWR ", " IORW ", " IORR ", " IOWR ", " IO ",
#endif #endif
#ifdef HAVE_CGROUP
" CGROUP ",
#endif
#ifdef HAVE_OOM
" OOM ",
#endif
"IO ",
"*** report bug! ***"
}; };
static int Process_getuid = -1; static int Process_getuid = -1;
static char* Process_pidFormat = "%7u "; #define ONE_K 1024
static char* Process_tpgidFormat = "%7u ";
void Process_getMaxPid() {
FILE* file = fopen(PROCDIR "/sys/kernel/pid_max", "r");
if (!file) return;
int maxPid = 4194303;
fscanf(file, "%32d", &maxPid);
fclose(file);
if (maxPid > 99999) {
Process_fieldTitles[PID] = " PID ";
Process_fieldTitles[PPID] = " PPID ";
Process_fieldTitles[TPGID] = " TPGID ";
Process_fieldTitles[TGID] = " TGID ";
Process_fieldTitles[PGRP] = " PGRP ";
Process_fieldTitles[SESSION] = " SESN ";
#ifdef HAVE_OOM
Process_fieldTitles[OOM] = " OOM ";
#endif
Process_pidFormat = "%7u ";
Process_tpgidFormat = "%7d ";
} else {
Process_fieldTitles[PID] = " PID ";
Process_fieldTitles[PPID] = " PPID ";
Process_fieldTitles[TPGID] = "TPGID ";
Process_fieldTitles[TGID] = " TGID ";
Process_fieldTitles[PGRP] = " PGRP ";
Process_fieldTitles[SESSION] = " SESN ";
#ifdef HAVE_OOM
Process_fieldTitles[OOM] = " OOM ";
#endif
Process_pidFormat = "%5u ";
Process_tpgidFormat = "%5d ";
}
}
#define ONE_K 1024L
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K) #define ONE_G (ONE_M * ONE_K)
#define ONE_DECIMAL_K 1000L static void Process_printLargeNumber(Process* this, RichString *str, unsigned long number) {
#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K)
#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K)
static void Process_humanNumber(RichString* str, unsigned long number, bool coloring) {
char buffer[11]; char buffer[11];
int len; int len;
if(number >= (1000 * ONE_M)) {
int largeNumberColor = CRT_colors[LARGE_NUMBER]; len = snprintf(buffer, 10, "%4.2fG ", (float)number / ONE_M);
int processMegabytesColor = CRT_colors[PROCESS_MEGABYTES]; RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len);
int processColor = CRT_colors[PROCESS]; } else if(number >= (100000)) {
if (!coloring) {
largeNumberColor = CRT_colors[PROCESS];
processMegabytesColor = CRT_colors[PROCESS];
}
if(number >= (10 * ONE_DECIMAL_M)) {
#ifdef __LP64__
if(number >= (100 * ONE_DECIMAL_G)) {
len = snprintf(buffer, 10, "%4ldT ", number / ONE_G);
RichString_appendn(str, largeNumberColor, buffer, len);
return;
} else if (number >= (1000 * ONE_DECIMAL_M)) {
len = snprintf(buffer, 10, "%4.1lfT ", (double)number / ONE_G);
RichString_appendn(str, largeNumberColor, buffer, len);
return;
}
#endif
if(number >= (100 * ONE_DECIMAL_M)) {
len = snprintf(buffer, 10, "%4ldG ", number / ONE_M);
RichString_appendn(str, largeNumberColor, buffer, len);
return;
}
len = snprintf(buffer, 10, "%4.1lfG ", (double)number / ONE_M);
RichString_appendn(str, largeNumberColor, buffer, len);
return;
} else if (number >= 100000) {
len = snprintf(buffer, 10, "%4ldM ", number / ONE_K); len = snprintf(buffer, 10, "%4ldM ", number / ONE_K);
RichString_appendn(str, processMegabytesColor, buffer, len); int attr = this->pl->highlightMegabytes
return; ? CRT_colors[PROCESS_MEGABYTES]
} else if (number >= 1000) { : CRT_colors[PROCESS];
RichString_appendn(str, attr, buffer, len);
} else if (this->pl->highlightMegabytes && number >= 1000) {
len = snprintf(buffer, 10, "%2ld", number/1000); len = snprintf(buffer, 10, "%2ld", number/1000);
RichString_appendn(str, processMegabytesColor, buffer, len); RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer, len);
number %= 1000; number %= 1000;
len = snprintf(buffer, 10, "%03lu ", number); len = snprintf(buffer, 10, "%03ld ", number);
RichString_appendn(str, processColor, buffer, len); RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
return;
}
len = snprintf(buffer, 10, "%5lu ", number);
RichString_appendn(str, processColor, buffer, len);
}
static void Process_colorNumber(RichString* str, unsigned long long number, bool coloring) {
char buffer[14];
int largeNumberColor = CRT_colors[LARGE_NUMBER];
int processMegabytesColor = CRT_colors[PROCESS_MEGABYTES];
int processColor = CRT_colors[PROCESS];
int processShadowColor = CRT_colors[PROCESS_SHADOW];
if (!coloring) {
largeNumberColor = CRT_colors[PROCESS];
processMegabytesColor = CRT_colors[PROCESS];
processShadowColor = CRT_colors[PROCESS];
}
if (number > 10000000000) {
snprintf(buffer, 13, "%11lld ", number / 1000);
RichString_appendn(str, largeNumberColor, buffer, 5);
RichString_appendn(str, processMegabytesColor, buffer+5, 3);
RichString_appendn(str, processColor, buffer+8, 4);
} else { } else {
snprintf(buffer, 13, "%11llu ", number); len = snprintf(buffer, 10, "%5ld ", number);
RichString_appendn(str, largeNumberColor, buffer, 2); RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
RichString_appendn(str, processMegabytesColor, buffer+2, 3);
RichString_appendn(str, processColor, buffer+5, 3);
RichString_appendn(str, processShadowColor, buffer+8, 4);
} }
} }
static double jiffy = 0.0; static double jiffy = 0.0;
static void Process_printTime(RichString* str, unsigned long long t) { static void Process_printTime(RichString* str, unsigned long t) {
if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK); if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
double jiffytime = 1.0 / jiffy; double jiffytime = 1.0 / jiffy;
double realTime = t * jiffytime; double realTime = t * jiffytime;
unsigned long long iRealTime = (unsigned long long) realTime; int iRealTime = (int) realTime;
unsigned long long hours = iRealTime / 3600; int hours = iRealTime / 3600;
int minutes = (iRealTime / 60) % 60; int minutes = (iRealTime / 60) % 60;
int seconds = iRealTime % 60; int seconds = iRealTime % 60;
int hundredths = (realTime - iRealTime) * 100; int hundredths = (realTime - iRealTime) * 100;
char buffer[11]; char buffer[11];
if (hours >= 100) {
snprintf(buffer, 10, "%7lluh ", hours);
RichString_append(str, CRT_colors[LARGE_NUMBER], buffer);
} else {
if (hours) { if (hours) {
snprintf(buffer, 10, "%2lluh", hours); snprintf(buffer, 10, "%2dh", hours);
RichString_append(str, CRT_colors[LARGE_NUMBER], buffer); RichString_append(str, CRT_colors[LARGE_NUMBER], buffer);
snprintf(buffer, 10, "%02d:%02d ", minutes, seconds); snprintf(buffer, 10, "%02d:%02d ", minutes, seconds);
} else { } else {
@ -429,31 +237,26 @@ static void Process_printTime(RichString* str, unsigned long long t) {
} }
RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer); RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer);
} }
}
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 = RichString_size(str); int start = str->len;
RichString_append(str, attr, this->comm); RichString_append(str, attr, this->comm);
if (this->pl->highlightBaseName) { if (this->pl->highlightBaseName) {
int finish = RichString_size(str) - 1; int finish = str->len - 1;
if (this->basenameOffset != -1) int space = RichString_findChar(str, ' ', start);
finish = (start + this->basenameOffset) - 1; if (space != -1)
int colon = RichString_findChar(str, ':', start); finish = space - 1;
if (colon != -1 && colon < finish) { for (;;) {
finish = colon; int slash = RichString_findChar(str, '/', start);
} else { if (slash == -1 || slash > finish)
for (int i = finish - start; i >= 0; i--) {
if (this->comm[i] == '/') {
start += i+1;
break; break;
} start = slash + 1;
}
} }
RichString_setAttrn(str, baseattr, start, finish); RichString_setAttrn(str, baseattr, start, finish);
} }
} }
static inline void Process_outputRate(RichString* str, int attr, char* buffer, int n, double rate, int coloring) { static inline void Process_outputRate(Process* this, RichString* str, int attr, char* buffer, int n, double rate) {
rate = rate / 1024; rate = rate / 1024;
if (rate < 0.01) if (rate < 0.01)
snprintf(buffer, n, " 0 "); snprintf(buffer, n, " 0 ");
@ -462,35 +265,30 @@ static inline void Process_outputRate(RichString* str, int attr, char* buffer, i
else if (rate <= 100) else if (rate <= 100)
snprintf(buffer, n, "%5.1f ", rate); snprintf(buffer, n, "%5.1f ", rate);
else { else {
Process_humanNumber(str, rate, coloring); Process_printLargeNumber(this, str, rate);
return; return;
} }
RichString_append(str, attr, buffer); RichString_append(str, attr, buffer);
} }
static void Process_writeField(Process* this, RichString* str, ProcessField field) { static void Process_writeField(Process* this, RichString* str, ProcessField field) {
char buffer[256]; buffer[255] = '\0'; char buffer[PROCESS_COMM_LEN];
int attr = CRT_colors[DEFAULT_COLOR]; int attr = CRT_colors[DEFAULT_COLOR];
int baseattr = CRT_colors[PROCESS_BASENAME]; int baseattr = CRT_colors[PROCESS_BASENAME];
int n = sizeof(buffer) - 1; int n = PROCESS_COMM_LEN;
bool coloring = this->pl->highlightMegabytes;
switch (field) { switch (field) {
case PID: snprintf(buffer, n, Process_pidFormat, this->pid); break; case PID: snprintf(buffer, n, "%5u ", this->pid); break;
case PPID: snprintf(buffer, n, Process_pidFormat, this->ppid); break; case PPID: snprintf(buffer, n, "%5u ", this->ppid); break;
case PGRP: snprintf(buffer, n, Process_pidFormat, this->pgrp); break; case PGRP: snprintf(buffer, n, "%5u ", this->pgrp); break;
case SESSION: snprintf(buffer, n, Process_pidFormat, this->session); break; case SESSION: snprintf(buffer, n, "%5u ", this->session); break;
case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break; case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break;
case TGID: snprintf(buffer, n, Process_pidFormat, this->tgid); break; case TGID: snprintf(buffer, n, "%5u ", this->tgid); break;
case TPGID: snprintf(buffer, n, Process_tpgidFormat, this->tpgid); break; case TPGID: snprintf(buffer, n, "%5d ", this->tpgid); break;
case MINFLT: Process_colorNumber(str, this->minflt, coloring); return; case PROCESSOR: snprintf(buffer, n, "%3d ", this->processor+1); break;
case CMINFLT: Process_colorNumber(str, this->cminflt, coloring); return;
case MAJFLT: Process_colorNumber(str, this->majflt, coloring); return;
case CMAJFLT: Process_colorNumber(str, this->cmajflt, coloring); return;
case PROCESSOR: snprintf(buffer, n, "%3d ", ProcessList_cpuId(this->pl, this->processor)); break;
case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break; case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break;
case COMM: { case COMM: {
if (this->pl->highlightThreads && Process_isThread(this)) { if (this->pl->highlightThreads && (this->pid != this->tgid || this->m_size == 0)) {
attr = CRT_colors[PROCESS_THREAD]; attr = CRT_colors[PROCESS_THREAD];
baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
} }
@ -500,26 +298,21 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
} else { } else {
char* buf = buffer; char* buf = buffer;
int maxIndent = 0; 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++) for (int i = 0; i < 32; i++)
if (indent & (1 << i)) if (this->indent & (1 << i))
maxIndent = i+1; maxIndent = i+1;
for (int i = 0; i < maxIndent - 1; i++) { for (int i = 0; i < maxIndent - 1; i++) {
int written; if (this->indent & (1 << i))
if (indent & (1 << i)) snprintf(buf, n, " | ");
written = snprintf(buf, n, "%s ", treeStr[TREE_STR_VERT]);
else else
written = snprintf(buf, n, " "); snprintf(buf, n, " ");
buf += written; buf += 4;
n -= written; n -= 4;
} }
const char* draw = treeStr[lastItem ? (this->pl->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE]; if (this->pl->direction == 1)
snprintf(buf, n, "%s%s ", draw, this->showChildren ? treeStr[TREE_STR_SHUT] : treeStr[TREE_STR_OPEN] ); snprintf(buf, n, " `- ");
else
snprintf(buf, n, " ,- ");
RichString_append(str, CRT_colors[PROCESS_TREE], buffer); RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
Process_writeCommand(this, attr, baseattr, str); Process_writeCommand(this, attr, baseattr, str);
return; return;
@ -546,25 +339,25 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
: attr; : attr;
break; break;
} }
case M_DRS: Process_humanNumber(str, this->m_drs * PAGE_SIZE_KB, coloring); return; case M_DRS: Process_printLargeNumber(this, str, this->m_drs * PAGE_SIZE); return;
case M_DT: Process_humanNumber(str, this->m_dt * PAGE_SIZE_KB, coloring); return; case M_DT: Process_printLargeNumber(this, str, this->m_dt * PAGE_SIZE); return;
case M_LRS: Process_humanNumber(str, this->m_lrs * PAGE_SIZE_KB, coloring); return; case M_LRS: Process_printLargeNumber(this, str, this->m_lrs * PAGE_SIZE); return;
case M_TRS: Process_humanNumber(str, this->m_trs * PAGE_SIZE_KB, coloring); return; case M_TRS: Process_printLargeNumber(this, str, this->m_trs * PAGE_SIZE); return;
case M_SIZE: Process_humanNumber(str, this->m_size * PAGE_SIZE_KB, coloring); return; case M_SIZE: Process_printLargeNumber(this, str, this->m_size * PAGE_SIZE); return;
case M_RESIDENT: Process_humanNumber(str, this->m_resident * PAGE_SIZE_KB, coloring); return; case M_RESIDENT: Process_printLargeNumber(this, str, this->m_resident * PAGE_SIZE); return;
case M_SHARE: Process_humanNumber(str, this->m_share * PAGE_SIZE_KB, coloring); return; case M_SHARE: Process_printLargeNumber(this, str, this->m_share * PAGE_SIZE); return;
case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break; case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break;
case USER: { case USER: {
if (Process_getuid != (int) this->st_uid) if (Process_getuid != this->st_uid)
attr = CRT_colors[PROCESS_SHADOW]; attr = CRT_colors[PROCESS_SHADOW];
if (this->user) { if (this->user) {
snprintf(buffer, n, "%-9s ", this->user); snprintf(buffer, n, "%-8s ", this->user);
} else { } else {
snprintf(buffer, n, "%-9d ", this->st_uid); snprintf(buffer, n, "%-8d ", this->st_uid);
} }
if (buffer[9] != '\0') { if (buffer[8] != '\0') {
buffer[9] = ' '; buffer[8] = ' ';
buffer[10] = '\0'; buffer[9] = '\0';
} }
break; break;
} }
@ -591,50 +384,23 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
} }
break; break;
} }
case STARTTIME: snprintf(buffer, n, "%s", this->starttime_show); break;
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
case CTID: snprintf(buffer, n, "%5u ", this->ctid); break; case VEID: snprintf(buffer, n, "%5u ", this->veid); break;
case VPID: snprintf(buffer, n, "%5u ", this->vpid); break; case VPID: snprintf(buffer, n, "%5u ", this->vpid); break;
#endif #endif
#ifdef HAVE_VSERVER
case VXID: snprintf(buffer, n, "%5u ", this->vxid); break;
#endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
case RCHAR: Process_colorNumber(str, this->io_rchar, coloring); return; case RCHAR: snprintf(buffer, n, "%10llu ", this->io_rchar); break;
case WCHAR: Process_colorNumber(str, this->io_wchar, coloring); return; case WCHAR: snprintf(buffer, n, "%10llu ", this->io_wchar); break;
case SYSCR: Process_colorNumber(str, this->io_syscr, coloring); return; case SYSCR: snprintf(buffer, n, "%10llu ", this->io_syscr); break;
case SYSCW: Process_colorNumber(str, this->io_syscw, coloring); return; case SYSCW: snprintf(buffer, n, "%10llu ", this->io_syscw); break;
case RBYTES: Process_colorNumber(str, this->io_read_bytes, coloring); return; case RBYTES: snprintf(buffer, n, "%10llu ", this->io_read_bytes); break;
case WBYTES: Process_colorNumber(str, this->io_write_bytes, coloring); return; case WBYTES: snprintf(buffer, n, "%10llu ", this->io_write_bytes); break;
case CNCLWB: Process_colorNumber(str, this->io_cancelled_write_bytes, coloring); return; case CNCLWB: snprintf(buffer, n, "%10llu ", this->io_cancelled_write_bytes); break;
case IO_READ_RATE: Process_outputRate(str, attr, buffer, n, this->io_rate_read_bps, coloring); return; case IO_READ_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps); return;
case IO_WRITE_RATE: Process_outputRate(str, attr, buffer, n, this->io_rate_write_bps, coloring); return; case IO_WRITE_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_write_bps); return;
case IO_RATE: Process_outputRate(str, attr, buffer, n, this->io_rate_read_bps + this->io_rate_write_bps, coloring); return; case IO_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps + this->io_rate_write_bps); return;
#endif #endif
#ifdef HAVE_CGROUP
case CGROUP: snprintf(buffer, n, "%-10s ", this->cgroup); break;
#endif
#ifdef HAVE_OOM
case OOM: snprintf(buffer, n, Process_pidFormat, this->oom); break;
#endif
case IO_PRIORITY: {
int klass = IOPriority_class(this->ioPriority);
if (klass == IOPRIO_CLASS_NONE) {
// see note [1] above
snprintf(buffer, n, "B%1d ", (int) (this->nice + 20) / 5);
} else if (klass == IOPRIO_CLASS_BE) {
snprintf(buffer, n, "B%1d ", IOPriority_data(this->ioPriority));
} else if (klass == IOPRIO_CLASS_RT) {
attr = CRT_colors[PROCESS_HIGH_PRIORITY];
snprintf(buffer, n, "R%1d ", IOPriority_data(this->ioPriority));
} else if (this->ioPriority == IOPriority_Idle) {
attr = CRT_colors[PROCESS_LOW_PRIORITY];
snprintf(buffer, n, "id ");
} else {
snprintf(buffer, n, "?? ");
}
break;
}
default: default:
snprintf(buffer, n, "- "); snprintf(buffer, n, "- ");
} }
@ -644,54 +410,61 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
static void Process_display(Object* cast, RichString* out) { static void Process_display(Object* cast, RichString* out) {
Process* this = (Process*) cast; Process* this = (Process*) cast;
ProcessField* fields = this->pl->fields; ProcessField* fields = this->pl->fields;
RichString_prune(out); RichString_init(out);
for (int i = 0; fields[i]; i++) for (int i = 0; fields[i]; i++)
Process_writeField(this, out, fields[i]); Process_writeField(this, out, fields[i]);
if (this->pl->shadowOtherUsers && (int)this->st_uid != Process_getuid) if (this->pl->shadowOtherUsers && this->st_uid != Process_getuid)
RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]); RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
if (this->tag == true) if (this->tag == true)
RichString_setAttr(out, CRT_colors[PROCESS_TAG]); RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
assert(out->chlen > 0); assert(out->len > 0);
} }
void Process_delete(Object* cast) { void Process_delete(Object* cast) {
Process* this = (Process*) cast; Process* this = (Process*) cast;
assert (this != NULL); assert (this != NULL);
if (this->comm) free(this->comm); if (this->comm) free(this->comm);
#ifdef HAVE_CGROUP
if (this->cgroup) free(this->cgroup);
#endif
free(this); free(this);
} }
ObjectClass Process_class = {
.extends = Class(Object),
.display = Process_display,
.delete = Process_delete,
.compare = Process_compare
};
Process* Process_new(struct ProcessList_ *pl) { Process* Process_new(struct ProcessList_ *pl) {
Process* this = calloc(1, sizeof(Process)); Process* this = calloc(sizeof(Process), 1);
Object_setClass(this, Class(Process)); Object_setClass(this, PROCESS_CLASS);
((Object*)this)->display = Process_display;
((Object*)this)->delete = Process_delete;
this->pid = 0; this->pid = 0;
this->pl = pl; this->pl = pl;
this->tag = false; this->tag = false;
this->showChildren = true;
this->show = true;
this->updated = false; this->updated = false;
this->utime = 0; this->utime = 0;
this->stime = 0; this->stime = 0;
this->comm = NULL; this->comm = NULL;
this->basenameOffset = -1;
this->indent = 0; this->indent = 0;
#ifdef HAVE_CGROUP
this->cgroup = NULL;
#endif
if (Process_getuid == -1) Process_getuid = getuid(); if (Process_getuid == -1) Process_getuid = getuid();
return this; return this;
} }
Process* Process_clone(Process* this) {
Process* clone = malloc(sizeof(Process));
#if HAVE_TASKSTATS
this->io_rchar = 0;
this->io_wchar = 0;
this->io_syscr = 0;
this->io_syscw = 0;
this->io_read_bytes = 0;
this->io_rate_read_bps = 0;
this->io_rate_read_time = 0;
this->io_write_bytes = 0;
this->io_rate_write_bps = 0;
this->io_rate_write_time = 0;
this->io_cancelled_write_bytes = 0;
#endif
memcpy(clone, this, sizeof(Process));
this->comm = NULL;
this->pid = 0;
return clone;
}
void Process_toggleTag(Process* this) { void Process_toggleTag(Process* this) {
this->tag = this->tag == true ? false : true; this->tag = this->tag == true ? false : true;
} }
@ -705,92 +478,18 @@ bool Process_setPriority(Process* this, int priority) {
return (err == 0); return (err == 0);
} }
bool Process_changePriorityBy(Process* this, size_t delta) { unsigned long Process_getAffinity(Process* this) {
return Process_setPriority(this, this->nice + delta); unsigned long mask = 0;
plpa_sched_getaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask);
return mask;
} }
IOPriority Process_updateIOPriority(Process* this) { bool Process_setAffinity(Process* this, unsigned long mask) {
IOPriority ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, this->pid); return (plpa_sched_setaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask) == 0);
this->ioPriority = ioprio;
return ioprio;
} }
bool Process_setIOPriority(Process* this, IOPriority ioprio) { void Process_sendSignal(Process* this, int signal) {
syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, this->pid, ioprio); kill(this->pid, signal);
return (Process_updateIOPriority(this) == ioprio);
}
/*
[1] Note that before kernel 2.6.26 a process that has not asked for
an io priority formally uses "none" as scheduling class, but the
io scheduler will treat such processes as if it were in the best
effort class. The priority within the best effort class will be
dynamically derived from the cpu nice level of the process:
io_priority = (cpu_nice + 20) / 5. -- From ionice(1) man page
*/
#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority)
#ifdef HAVE_LIBHWLOC
Affinity* Process_getAffinity(Process* this) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
bool ok = (hwloc_linux_get_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
Affinity* affinity = NULL;
if (ok) {
affinity = Affinity_new();
if (hwloc_bitmap_last(cpuset) == -1) {
for (int i = 0; i < this->pl->cpuCount; i++) {
Affinity_add(affinity, i);
}
} else {
unsigned int id;
hwloc_bitmap_foreach_begin(id, cpuset);
Affinity_add(affinity, id);
hwloc_bitmap_foreach_end();
}
}
hwloc_bitmap_free(cpuset);
return affinity;
}
bool Process_setAffinity(Process* this, Affinity* affinity) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
for (int i = 0; i < affinity->used; i++) {
hwloc_bitmap_set(cpuset, affinity->cpus[i]);
}
bool ok = (hwloc_linux_set_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
hwloc_bitmap_free(cpuset);
return ok;
}
#elif HAVE_NATIVE_AFFINITY
Affinity* Process_getAffinity(Process* this) {
cpu_set_t cpuset;
bool ok = (sched_getaffinity(this->pid, sizeof(cpu_set_t), &cpuset) == 0);
if (!ok) return NULL;
Affinity* affinity = Affinity_new();
for (int i = 0; i < this->pl->cpuCount; i++) {
if (CPU_ISSET(i, &cpuset))
Affinity_add(affinity, i);
}
return affinity;
}
bool Process_setAffinity(Process* this, Affinity* affinity) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
for (int i = 0; i < affinity->used; i++) {
CPU_SET(affinity->cpus[i], &cpuset);
}
bool ok = (sched_setaffinity(this->pid, sizeof(unsigned long), &cpuset) == 0);
return ok;
}
#endif
void Process_sendSignal(Process* this, size_t sgn) {
kill(this->pid, (int) sgn);
} }
int Process_pidCompare(const void* v1, const void* v2) { int Process_pidCompare(const void* v1, const void* v2) {
@ -816,13 +515,9 @@ int Process_compare(const void* v1, const void* v2) {
case PPID: case PPID:
return (p1->ppid - p2->ppid); return (p1->ppid - p2->ppid);
case USER: case USER:
return strcmp(p1->user ? p1->user : "", p2->user ? p2->user : ""); return strcmp(p1->user, p2->user);
case PRIORITY: case PRIORITY:
return (p1->priority - p2->priority); return (p1->priority - p2->priority);
case PROCESSOR:
return (p1->processor - p2->processor);
case SESSION:
return (p1->session - p2->session);
case STATE: case STATE:
return (p1->state - p2->state); return (p1->state - p2->state);
case NICE: case NICE:
@ -855,22 +550,12 @@ int Process_compare(const void* v1, const void* v2) {
return strcmp(p1->comm, p2->comm); return strcmp(p1->comm, p2->comm);
case NLWP: case NLWP:
return (p1->nlwp - p2->nlwp); return (p1->nlwp - p2->nlwp);
case STARTTIME: {
if (p1->starttime_ctime == p2->starttime_ctime)
return (p1->pid - p2->pid);
else
return (p1->starttime_ctime - p2->starttime_ctime);
}
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
case CTID: case VEID:
return (p1->ctid - p2->ctid); return (p1->veid - p2->veid);
case VPID: case VPID:
return (p1->vpid - p2->vpid); return (p1->vpid - p2->vpid);
#endif #endif
#ifdef HAVE_VSERVER
case VXID:
return (p1->vxid - p2->vxid);
#endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff; case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff;
case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff; case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff;
@ -883,16 +568,7 @@ int Process_compare(const void* v1, const void* v2) {
case IO_WRITE_RATE: diff = p2->io_rate_write_bps - p1->io_rate_write_bps; goto test_diff; case IO_WRITE_RATE: diff = p2->io_rate_write_bps - p1->io_rate_write_bps; goto test_diff;
case IO_RATE: diff = (p2->io_rate_read_bps + p2->io_rate_write_bps) - (p1->io_rate_read_bps + p1->io_rate_write_bps); goto test_diff; case IO_RATE: diff = (p2->io_rate_read_bps + p2->io_rate_write_bps) - (p1->io_rate_read_bps + p1->io_rate_write_bps); goto test_diff;
#endif #endif
#ifdef HAVE_CGROUP
case CGROUP:
return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : "");
#endif
#ifdef HAVE_OOM
case OOM:
return (p1->oom - p2->oom);
#endif
case IO_PRIORITY:
return Process_effectiveIOPriority(p1) - Process_effectiveIOPriority(p2);
default: default:
return (p1->pid - p2->pid); return (p1->pid - p2->pid);
} }

228
Process.h
View File

@ -4,43 +4,43 @@
#define HEADER_Process #define HEADER_Process
/* /*
htop - Process.h htop - Process.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifdef HAVE_LIBHWLOC #define _GNU_SOURCE
#endif #include "ProcessList.h"
#include "Object.h"
#include "CRT.h"
#include "String.h"
#include "RichString.h"
#include "debug.h"
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>
#include <pwd.h>
#include <sched.h>
#include <plpa.h>
// This works only with glibc 2.1+. On earlier versions // This works only with glibc 2.1+. On earlier versions
// the behavior is similar to have a hardcoded page size. // the behavior is similar to have a hardcoded page size.
#ifndef PAGE_SIZE #ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) ) #define PAGE_SIZE ( sysconf(_SC_PAGESIZE) / 1024 )
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
#include "Object.h"
#include "Affinity.h"
#include "IOPriority.h"
#include <sys/types.h>
#define PROCESS_FLAG_IO 1
#define PROCESS_FLAG_IOPRIO 2
#define PROCESS_FLAG_OPENVZ 4
#define PROCESS_FLAG_VSERVER 8
#define PROCESS_FLAG_CGROUP 16
#ifndef Process_isKernelThread
#define Process_isKernelThread(_process) (_process->pgrp == 0)
#endif #endif
#ifndef Process_isUserlandThread #define PROCESS_COMM_LEN 300
#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
#endif
#ifndef Process_isThread
#define Process_isThread(_process) (Process_isUserlandThread(_process) || Process_isKernelThread(_process))
#endif
typedef enum ProcessField_ { typedef enum ProcessField_ {
PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME, PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME,
@ -49,21 +49,11 @@ typedef enum ProcessField_ {
PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM, PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
USER, TIME, NLWP, TGID, USER, TIME, NLWP, TGID,
#ifdef HAVE_OPENVZ #ifdef HAVE_OPENVZ
CTID, VPID, VEID, VPID,
#endif
#ifdef HAVE_VSERVER
VXID,
#endif #endif
#ifdef HAVE_TASKSTATS #ifdef HAVE_TASKSTATS
RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE, RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE,
#endif #endif
#ifdef HAVE_CGROUP
CGROUP,
#endif
#ifdef HAVE_OOM
OOM,
#endif
IO_PRIORITY,
LAST_PROCESSFIELD LAST_PROCESSFIELD
} ProcessField; } ProcessField;
@ -73,86 +63,36 @@ typedef struct Process_ {
Object super; Object super;
struct ProcessList_ *pl; struct ProcessList_ *pl;
bool updated;
pid_t pid; unsigned int pid;
char* comm; char* comm;
int indent; int indent;
char state; char state;
bool tag; bool tag;
bool showChildren; unsigned int ppid;
bool show;
pid_t ppid;
unsigned int pgrp; unsigned int pgrp;
unsigned int session; unsigned int session;
unsigned int tty_nr; unsigned int tty_nr;
pid_t tgid; unsigned int tgid;
int tpgid; int tpgid;
unsigned long int flags; unsigned long int flags;
#ifdef DEBUG
uid_t st_uid;
float percent_cpu;
float percent_mem;
char* user;
unsigned long long int utime;
unsigned long long int stime;
unsigned long long int cutime;
unsigned long long int cstime;
long int priority;
long int nice;
long int nlwp;
IOPriority ioPriority;
char starttime_show[8];
time_t starttime_ctime;
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
int processor;
long m_size;
long m_resident;
long m_share;
long m_trs;
long m_drs;
long m_lrs;
long m_dt;
#ifdef HAVE_OPENVZ
unsigned int ctid;
unsigned int vpid;
#endif
#ifdef HAVE_VSERVER
unsigned int vxid;
#endif
#ifdef HAVE_CGROUP
char* cgroup;
#endif
#ifdef HAVE_OOM
unsigned int oom;
#endif
int exit_signal;
int basenameOffset;
bool updated;
unsigned long int minflt; unsigned long int minflt;
unsigned long int cminflt; unsigned long int cminflt;
unsigned long int majflt; unsigned long int majflt;
unsigned long int cmajflt; unsigned long int cmajflt;
#endif
unsigned long int utime;
unsigned long int stime;
long int cutime;
long int cstime;
long int priority;
long int nice;
long int nlwp;
#ifdef DEBUG #ifdef DEBUG
long int itrealvalue; long int itrealvalue;
unsigned long int starttime;
unsigned long int vsize; unsigned long int vsize;
long int rss; long int rss;
unsigned long int rlim; unsigned long int rlim;
@ -169,68 +109,68 @@ typedef struct Process_ {
unsigned long int nswap; unsigned long int nswap;
unsigned long int cnswap; unsigned long int cnswap;
#endif #endif
int exit_signal;
int processor;
int m_size;
int m_resident;
int m_share;
int m_trs;
int m_drs;
int m_lrs;
int m_dt;
uid_t st_uid;
float percent_cpu;
float percent_mem;
char* user;
#ifdef HAVE_OPENVZ
unsigned int veid;
unsigned int vpid;
#endif
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
} Process; } Process;
extern const char *Process_fieldNames[]; #ifdef DEBUG
extern char* PROCESS_CLASS;
#else
#define PROCESS_CLASS NULL
#endif
extern const int Process_fieldFlags[]; extern char *Process_fieldNames[];
extern const char *Process_fieldTitles[]; extern char *Process_fieldTitles[];
#define ONE_K 1024
void Process_getMaxPid();
#define ONE_K 1024L
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K) #define ONE_G (ONE_M * ONE_K)
#define ONE_DECIMAL_K 1000L
#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K)
#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K)
void Process_delete(Object* cast); void Process_delete(Object* cast);
extern ObjectClass Process_class;
Process* Process_new(struct ProcessList_ *pl); Process* Process_new(struct ProcessList_ *pl);
Process* Process_clone(Process* this);
void Process_toggleTag(Process* this); void Process_toggleTag(Process* this);
bool Process_setPriority(Process* this, int priority); bool Process_setPriority(Process* this, int priority);
bool Process_changePriorityBy(Process* this, size_t delta); unsigned long Process_getAffinity(Process* this);
IOPriority Process_updateIOPriority(Process* this); bool Process_setAffinity(Process* this, unsigned long mask);
bool Process_setIOPriority(Process* this, IOPriority ioprio); void Process_sendSignal(Process* this, int signal);
/*
[1] Note that before kernel 2.6.26 a process that has not asked for
an io priority formally uses "none" as scheduling class, but the
io scheduler will treat such processes as if it were in the best
effort class. The priority within the best effort class will be
dynamically derived from the cpu nice level of the process:
extern io_priority;
*/
#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority)
#ifdef HAVE_LIBHWLOC
Affinity* Process_getAffinity(Process* this);
bool Process_setAffinity(Process* this, Affinity* affinity);
#elif HAVE_NATIVE_AFFINITY
Affinity* Process_getAffinity(Process* this);
bool Process_setAffinity(Process* this, Affinity* affinity);
#endif
void Process_sendSignal(Process* this, size_t sgn);
int Process_pidCompare(const void* v1, const void* v2); int Process_pidCompare(const void* v1, const void* v2);

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,30 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Vector.h" #ifndef CONFIG_H
#include "Hashtable.h" #define CONFIG_H
#include "UsersTable.h" #include "config.h"
#include "Panel.h" #endif
#include "Process.h" #include "Process.h"
#include "Vector.h"
#include "UsersTable.h"
#include "Hashtable.h"
#include "String.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>
#include <sys/utsname.h>
#include <stdarg.h>
#include "debug.h"
#include <assert.h>
#ifndef PROCDIR #ifndef PROCDIR
#define PROCDIR "/proc" #define PROCDIR "/proc"
@ -35,73 +54,50 @@ in the source distribution for its full text.
#define MAX_READ 2048 #define MAX_READ 2048
#endif #endif
#ifndef ProcessList_cpuId #ifndef PER_PROCESSOR_FIELDS
#define ProcessList_cpuId(pl, cpu) ((pl)->countCPUsFromZero ? (cpu) : (cpu)+1) #define PER_PROCESSOR_FIELDS 22
#endif #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 struct CPUData_ {
unsigned long long int totalTime;
unsigned long long int userTime;
unsigned long long int systemTime;
unsigned long long int systemAllTime;
unsigned long long int idleAllTime;
unsigned long long int idleTime;
unsigned long long int niceTime;
unsigned long long int ioWaitTime;
unsigned long long int irqTime;
unsigned long long int softIrqTime;
unsigned long long int stealTime;
unsigned long long int guestTime;
unsigned long long int totalPeriod; #ifdef DEBUG_PROC
unsigned long long int userPeriod; typedef int(*vxscanf)(void*, const char*, va_list);
unsigned long long int systemPeriod; #endif
unsigned long long int systemAllPeriod;
unsigned long long int idleAllPeriod;
unsigned long long int idlePeriod;
unsigned long long int nicePeriod;
unsigned long long int ioWaitPeriod;
unsigned long long int irqPeriod;
unsigned long long int softIrqPeriod;
unsigned long long int stealPeriod;
unsigned long long int guestPeriod;
} CPUData;
typedef struct ProcessList_ { typedef struct ProcessList_ {
const char **treeStr;
Vector* processes; Vector* processes;
Vector* processes2; Vector* processes2;
Hashtable* processTable; Hashtable* processTable;
Process* prototype;
UsersTable* usersTable; UsersTable* usersTable;
Panel* panel; int processorCount;
int following;
uid_t userId;
const char* incFilter;
Hashtable* pidWhiteList;
int cpuCount;
int totalTasks; int totalTasks;
int userlandThreads;
int kernelThreads;
int runningTasks; int runningTasks;
#ifdef HAVE_LIBHWLOC // Must match number of PER_PROCESSOR_FIELDS constant
hwloc_topology_t topology; unsigned long long int* totalTime;
bool topologyOk; unsigned long long int* userTime;
#endif unsigned long long int* systemTime;
CPUData* cpus; unsigned long long int* systemAllTime;
unsigned long long int* idleAllTime;
unsigned long long int* idleTime;
unsigned long long int* niceTime;
unsigned long long int* ioWaitTime;
unsigned long long int* irqTime;
unsigned long long int* softIrqTime;
unsigned long long int* stealTime;
unsigned long long int* totalPeriod;
unsigned long long int* userPeriod;
unsigned long long int* systemPeriod;
unsigned long long int* systemAllPeriod;
unsigned long long int* idleAllPeriod;
unsigned long long int* idlePeriod;
unsigned long long int* nicePeriod;
unsigned long long int* ioWaitPeriod;
unsigned long long int* irqPeriod;
unsigned long long int* softIrqPeriod;
unsigned long long int* stealPeriod;
unsigned long long int totalMem; unsigned long long int totalMem;
unsigned long long int usedMem; unsigned long long int usedMem;
@ -113,14 +109,11 @@ typedef struct ProcessList_ {
unsigned long long int usedSwap; unsigned long long int usedSwap;
unsigned long long int freeSwap; unsigned long long int freeSwap;
int flags;
ProcessField* fields; ProcessField* fields;
ProcessField sortKey; ProcessField sortKey;
int direction; int direction;
bool hideThreads; bool hideThreads;
bool shadowOtherUsers; bool shadowOtherUsers;
bool showThreadNames;
bool showingThreadNames;
bool hideKernelThreads; bool hideKernelThreads;
bool hideUserlandThreads; bool hideUserlandThreads;
bool treeView; bool treeView;
@ -128,29 +121,36 @@ typedef struct ProcessList_ {
bool highlightMegabytes; bool highlightMegabytes;
bool highlightThreads; bool highlightThreads;
bool detailedCPUTime; bool detailedCPUTime;
bool countCPUsFromZero; #ifdef DEBUG_PROC
bool updateProcessNames; FILE* traceFile;
bool accountGuestInCPUMeter; #endif
bool userOnly;
} ProcessList; } ProcessList;
#ifdef DEBUG_PROC
extern const char *ProcessList_treeStrAscii[TREE_STR_COUNT]; #define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
extern const char *ProcessList_treeStrUtf8[TREE_STR_COUNT]; #else
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList); #ifndef ProcessList_read
#define ProcessList_fopen(this, path, mode) fopen(path, mode)
#define ProcessList_read(this, buffer, format, ...) sscanf(buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) fscanf(file, format, ## __VA_ARGS__ )
#endif
#endif
ProcessList* ProcessList_new(UsersTable* usersTable);
void ProcessList_delete(ProcessList* this); void ProcessList_delete(ProcessList* this);
void ProcessList_setPanel(ProcessList* this, Panel* panel);
void ProcessList_invertSortOrder(ProcessList* this); void ProcessList_invertSortOrder(ProcessList* this);
void ProcessList_printHeader(ProcessList* this, RichString* header); RichString ProcessList_printHeader(ProcessList* this);
Process* ProcessList_get(ProcessList* this, int idx); Process* ProcessList_get(ProcessList* this, int index);
int ProcessList_size(ProcessList* this); int ProcessList_size(ProcessList* this);
@ -160,29 +160,8 @@ void ProcessList_sort(ProcessList* this);
#endif #endif
#ifdef HAVE_OPENVZ
#endif
#ifdef HAVE_CGROUP
#endif
#ifdef HAVE_VSERVER
#endif
#ifdef HAVE_OOM
#endif
void ProcessList_scan(ProcessList* this); void ProcessList_scan(ProcessList* this);
ProcessField ProcessList_keyAt(ProcessList* this, int at); ProcessField ProcessList_keyAt(ProcessList* this, int at);
void ProcessList_expandTree(ProcessList* this);
void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, bool userOnly, uid_t userId, const char* incFilter);
#endif #endif

28
README
View File

@ -1,17 +1,11 @@
htop htop
==== by Hisham Muhammad <loderunner@users.sourceforge.net>
by Hisham Muhammad <hisham@gobolinux.org> May, 2004 - July, 2006
May, 2004 - January, 2014
Note
----
![Alert](http://i.imgur.com/ugIqB9s.png) **Mac users, [click here](https://www.bountysource.com/fundraisers/554-mac-os-x-support-in-the-official-htop-1-x-tree)!** The htop version you are using is a 5-year old fork -- help bring htop 1.x to the Mac!
Introduction Introduction
------------ ~~~~~~~~~~~~
This is htop, an interactive process viewer. This is htop, an interactive process viewer.
It requires ncurses. It is tested with Linux 2.6, It requires ncurses. It is tested with Linux 2.6,
@ -21,15 +15,13 @@ with the 2.4 series.
Note that, while, htop is Linux specific -- it is based Note that, while, htop is Linux specific -- it is based
on the Linux /proc filesystem -- it is also reported to work on the Linux /proc filesystem -- it is also reported to work
with FreeBSD systems featuring a Linux-compatible /proc. with FreeBSD systems featuring a Linux-compatible /proc.
This is, however, unsupported. Contact the packager for your
system when reporting problems on platforms other than Linux.
This software has evolved considerably during the last years, This software has evolved considerably during the last months,
and is reasonably complete, but there is still room for and is reasonably complete, but there is still room for
improvement. Read the TODO file to see what's known to be missing. improvement. Read the TODO file to see what's known to be missing.
Comparison between 'htop' and 'top' Comparison between 'htop' and 'top'
----------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* In 'htop' you can scroll the list vertically and horizontally * In 'htop' you can scroll the list vertically and horizontally
to see all processes and full command lines. to see all processes and full command lines.
@ -46,15 +38,11 @@ Comparison between 'htop' and 'top'
* 'top' is older, hence, more tested. * 'top' is older, hence, more tested.
Compilation instructions Compilation instructions
------------------------ ~~~~~~~~~~~~~~~~~~~~~~~~
This program is distributed as a standard autotools-based package. This program is distributed as a standard autotools-based package.
See the INSTALL file for detailed instructions, but you are See the INSTALL file for detailed instructions, but you are
probably used to the common `./configure`/`make`/`make install` routine. probably used to the common "configure/make/make install" routine.
When fetching the code from the development repository, you need
to run the `./autogen.sh` script, which in turn requires autotools
to be installed.
See the manual page (man htop) or the on-line help ('F1' or 'h' See the manual page (man htop) or the on-line help ('F1' or 'h'
inside htop) for a list of supported key commands. inside htop) for a list of supported key commands.

View File

@ -1 +0,0 @@
README

View File

@ -1,59 +1,45 @@
/*
htop - RichString.c
(C) 2004,2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#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 "debug.h"
#include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <wchar.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
/*{ /*{
#include "config.h"
#include <ctype.h>
#include <assert.h> #define RichString_init(this) (this)->len = 0
#ifdef HAVE_NCURSESW_CURSES_H #define RichString_initVal(this) (this).len = 0
#include <ncursesw/curses.h>
#elif HAVE_NCURSES_NCURSES_H
#include <ncurses/ncurses.h>
#elif HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#elif HAVE_NCURSES_H
#include <ncurses.h>
#elif HAVE_CURSES_H
#include <curses.h>
#endif
#define RichString_size(this) ((this)->chlen)
#define RichString_sizeVal(this) ((this).chlen)
#define RichString_begin(this) RichString (this); (this).chlen = 0; (this).chptr = (this).chstr;
#define RichString_beginAllocated(this) (this).chlen = 0; (this).chptr = (this).chstr;
#define RichString_end(this) RichString_prune(&(this));
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr) #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).chptr + off, n) #define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255) #define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
#define CharType cchar_t
#else #else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr) #define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n) #define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i]) #define RichString_getCharVal(this, i) (this.chstr[i])
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
#define CharType chtype
#endif #endif
typedef struct RichString_ { typedef struct RichString_ {
int chlen; int len;
CharType chstr[RICHSTRING_MAXLEN+1]; #ifdef HAVE_LIBNCURSESW
CharType* chptr; cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
}*/ }*/
@ -62,46 +48,25 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
#define charBytes(n) (sizeof(CharType) * (n))
static inline void RichString_setLen(RichString* this, int len) {
if (this->chlen <= RICHSTRING_MAXLEN) {
if (len > RICHSTRING_MAXLEN) {
this->chptr = malloc(charBytes(len+1));
memcpy(this->chptr, this->chstr, charBytes(this->chlen+1));
}
} else {
if (len <= RICHSTRING_MAXLEN) {
memcpy(this->chstr, this->chptr, charBytes(this->chlen));
free(this->chptr);
this->chptr = this->chstr;
} else {
this->chptr = realloc(this->chptr, charBytes(len+1));
}
}
RichString_setChar(this, len, 0);
this->chlen = len;
}
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) { inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
wchar_t data[len+1]; wchar_t data[RICHSTRING_MAXLEN];
len = mbstowcs(data, data_c, len); len = mbstowcs(data, data_c, RICHSTRING_MAXLEN);
if (len<0) if (len<0)
return; return;
int newLen = from + len; int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
RichString_setLen(this, newLen); for (int i = this->len, j = 0; i < last; i++, j++) {
memset(&this->chptr[from], 0, sizeof(CharType) * (newLen - from)); memset(&this->chstr[i], 0, sizeof(this->chstr[i]));
for (int i = from, j = 0; i < newLen; i++, j++) { this->chstr[i].chars[0] = data[j];
this->chptr[i].chars[0] = data[j]; this->chstr[i].attr = attrs;
this->chptr[i].attr = attrs;
} }
this->chptr[newLen].chars[0] = 0; this->chstr[last].chars[0] = 0;
this->len = last;
} }
inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) { inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
cchar_t* ch = this->chptr + start; cchar_t* ch = this->chstr + start;
for (int i = start; i <= finish; i++) { for (int i = start; i <= finish; i++) {
ch->attr = attrs; ch->attr = attrs;
ch++; ch++;
@ -110,8 +75,8 @@ inline void RichString_setAttrn(RichString* this, int attrs, int start, int fini
int RichString_findChar(RichString *this, char c, int start) { int RichString_findChar(RichString *this, char c, int start) {
wchar_t wc = btowc(c); wchar_t wc = btowc(c);
cchar_t* ch = this->chptr + start; cchar_t* ch = this->chstr + start;
for (int i = start; i < this->chlen; i++) { for (int i = start; i < this->len; i++) {
if (ch->chars[0] == wc) if (ch->chars[0] == wc)
return i; return i;
ch++; ch++;
@ -121,16 +86,16 @@ int RichString_findChar(RichString* this, char c, int start) {
#else #else
static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) { inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
int newLen = from + len; int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
RichString_setLen(this, newLen); for (int i = this->len, j = 0; i < last; i++, j++)
for (int i = from, j = 0; i < newLen; i++, j++) this->chstr[i] = data_c[j] | attrs;
this->chptr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs; this->chstr[last] = 0;
this->chptr[newLen] = 0; this->len = last;
} }
void RichString_setAttrn(RichString *this, int attrs, int start, int finish) { void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
chtype* ch = this->chptr + start; chtype* ch = this->chstr + start;
for (int i = start; i <= finish; i++) { for (int i = start; i <= finish; i++) {
*ch = (*ch & 0xff) | attrs; *ch = (*ch & 0xff) | attrs;
ch++; ch++;
@ -138,9 +103,9 @@ void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
} }
int RichString_findChar(RichString *this, char c, int start) { int RichString_findChar(RichString *this, char c, int start) {
chtype* ch = this->chptr + start; chtype* ch = this->chstr + start;
for (int i = start; i < this->chlen; i++) { for (int i = start; i < this->len; i++) {
if ((*ch & 0xff) == (chtype) c) if ((*ch & 0xff) == c)
return i; return i;
ch++; ch++;
} }
@ -149,26 +114,22 @@ int RichString_findChar(RichString* this, char c, int start) {
#endif #endif
void RichString_prune(RichString* this) {
if (this->chlen > RICHSTRING_MAXLEN)
free(this->chptr);
this->chptr = this->chstr;
this->chlen = 0;
RichString_setChar(this, 0, 0);
}
void RichString_setAttr(RichString *this, int attrs) { void RichString_setAttr(RichString *this, int attrs) {
RichString_setAttrn(this, attrs, 0, this->chlen - 1); RichString_setAttrn(this, attrs, 0, this->len - 1);
} }
void RichString_append(RichString* this, int attrs, const char* data) { inline void RichString_append(RichString* this, int attrs, char* data) {
RichString_writeFrom(this, attrs, data, this->chlen, strlen(data)); RichString_appendn(this, attrs, data, strlen(data));
} }
void RichString_appendn(RichString* this, int attrs, const char* data, int len) { void RichString_write(RichString* this, int attrs, char* data) {
RichString_writeFrom(this, attrs, data, this->chlen, len); RichString_init(this);
RichString_append(this, attrs, data);
} }
void RichString_write(RichString* this, int attrs, const char* data) { RichString RichString_quickString(int attrs, char* data) {
RichString_writeFrom(this, attrs, data, 0, strlen(data)); RichString str;
RichString_initVal(str);
RichString_write(&str, attrs, data);
return str;
} }

View File

@ -2,56 +2,46 @@
#ifndef HEADER_RichString #ifndef HEADER_RichString
#define HEADER_RichString #define HEADER_RichString
/*
htop - RichString.h
(C) 2004,2011 Hisham H. Muhammad #ifndef CONFIG_H
Released under the GNU GPL, see the COPYING file #define CONFIG_H
in the source distribution for its full text. #include "config.h"
*/ #endif
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include "debug.h"
#include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <wchar.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
#include "config.h"
#include <ctype.h>
#include <assert.h> #define RichString_init(this) (this)->len = 0
#ifdef HAVE_NCURSESW_CURSES_H #define RichString_initVal(this) (this).len = 0
#include <ncursesw/curses.h>
#elif HAVE_NCURSES_NCURSES_H
#include <ncurses/ncurses.h>
#elif HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#elif HAVE_NCURSES_H
#include <ncurses.h>
#elif HAVE_CURSES_H
#include <curses.h>
#endif
#define RichString_size(this) ((this)->chlen)
#define RichString_sizeVal(this) ((this).chlen)
#define RichString_begin(this) RichString (this); (this).chlen = 0; (this).chptr = (this).chstr;
#define RichString_beginAllocated(this) (this).chlen = 0; (this).chptr = (this).chstr;
#define RichString_end(this) RichString_prune(&(this));
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr) #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).chptr + off, n) #define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255) #define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
#define CharType cchar_t
#else #else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr) #define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n) #define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i]) #define RichString_getCharVal(this, i) (this.chstr[i])
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
#define CharType chtype
#endif #endif
typedef struct RichString_ { typedef struct RichString_ {
int chlen; int len;
CharType chstr[RICHSTRING_MAXLEN+1]; #ifdef HAVE_LIBNCURSESW
CharType* chptr; cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
@ -59,30 +49,30 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
#define charBytes(n) (sizeof(CharType) * (n))
#ifdef HAVE_LIBNCURSESW #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); extern void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start); int RichString_findChar(RichString *this, char c, int start);
#else #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); void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start); int RichString_findChar(RichString *this, char c, int start);
#endif #endif
void RichString_prune(RichString* this);
void RichString_setAttr(RichString *this, int attrs); void RichString_setAttr(RichString *this, int attrs);
void RichString_append(RichString* this, int attrs, const char* data); extern void RichString_append(RichString* this, int attrs, char* data);
void RichString_appendn(RichString* this, int attrs, const char* data, int len); void RichString_write(RichString* this, int attrs, char* data);
void RichString_write(RichString* this, int attrs, const char* data); RichString RichString_quickString(int attrs, char* data);
#endif #endif

View File

@ -1,24 +1,22 @@
/* /*
htop - ScreenManager.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ScreenManager.h" #include "ScreenManager.h"
#include "Panel.h" #include "Panel.h"
#include "Object.h" #include "Object.h"
#include "Vector.h"
#include "FunctionBar.h"
#include "debug.h"
#include <assert.h> #include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
/*{ /*{
#include "FunctionBar.h"
#include "Vector.h"
#include "Header.h"
typedef enum Orientation_ { typedef enum Orientation_ {
VERTICAL, VERTICAL,
@ -31,19 +29,16 @@ typedef struct ScreenManager_ {
int x2; int x2;
int y2; int y2;
Orientation orientation; Orientation orientation;
Vector* panels; Vector* items;
Vector* fuBars; Vector* fuBars;
int panelCount; int itemCount;
const FunctionBar* fuBar; FunctionBar* fuBar;
const Header* header;
time_t lastScan;
bool owner; bool owner;
bool allowFocusChange;
} ScreenManager; } ScreenManager;
}*/ }*/
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, bool owner) { ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, bool owner) {
ScreenManager* this; ScreenManager* this;
this = malloc(sizeof(ScreenManager)); this = malloc(sizeof(ScreenManager));
this->x1 = x1; this->x1 = x1;
@ -52,30 +47,28 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori
this->y2 = y2; this->y2 = y2;
this->fuBar = NULL; this->fuBar = NULL;
this->orientation = orientation; this->orientation = orientation;
this->panels = Vector_new(Class(Panel), owner, DEFAULT_SIZE); this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
this->fuBars = Vector_new(Class(FunctionBar), true, DEFAULT_SIZE); this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
this->panelCount = 0; this->itemCount = 0;
this->header = header;
this->owner = owner; this->owner = owner;
this->allowFocusChange = true;
return this; return this;
} }
void ScreenManager_delete(ScreenManager* this) { void ScreenManager_delete(ScreenManager* this) {
Vector_delete(this->panels); Vector_delete(this->items);
Vector_delete(this->fuBars); Vector_delete(this->fuBars);
free(this); free(this);
} }
inline int ScreenManager_size(ScreenManager* this) { inline int ScreenManager_size(ScreenManager* this) {
return this->panelCount; return this->itemCount;
} }
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) { void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
int lastX = 0; int lastX = 0;
if (this->panelCount > 0) { if (this->itemCount > 0) {
Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1); Panel* last = (Panel*) Vector_get(this->items, this->itemCount - 1);
lastX = last->x + last->w + 1; lastX = last->x + last->w + 1;
} }
if (size > 0) { if (size > 0) {
@ -86,22 +79,22 @@ void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int
Panel_move(item, lastX, this->y1); Panel_move(item, lastX, this->y1);
} }
// TODO: VERTICAL // TODO: VERTICAL
Vector_add(this->panels, item); Vector_add(this->items, item);
if (fuBar) if (fuBar)
Vector_add(this->fuBars, fuBar); Vector_add(this->fuBars, fuBar);
else else
Vector_add(this->fuBars, FunctionBar_new(NULL, NULL, NULL)); Vector_add(this->fuBars, FunctionBar_new(0, NULL, NULL, NULL));
if (!this->fuBar && fuBar) this->fuBar = fuBar; if (!this->fuBar && fuBar) this->fuBar = fuBar;
item->needsRedraw = true; item->needsRedraw = true;
this->panelCount++; this->itemCount++;
} }
Panel* ScreenManager_remove(ScreenManager* this, int idx) { Panel* ScreenManager_remove(ScreenManager* this, int index) {
assert(this->panelCount > idx); assert(this->itemCount > index);
Panel* panel = (Panel*) Vector_remove(this->panels, idx); Panel* panel = (Panel*) Vector_remove(this->items, index);
Vector_remove(this->fuBars, idx); Vector_remove(this->fuBars, index);
this->fuBar = NULL; this->fuBar = NULL;
this->panelCount--; this->itemCount--;
return panel; return panel;
} }
@ -110,15 +103,15 @@ void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
this->y1 = y1; this->y1 = y1;
this->x2 = x2; this->x2 = x2;
this->y2 = y2; this->y2 = y2;
int panels = this->panelCount; int items = this->itemCount;
int lastX = 0; int lastX = 0;
for (int i = 0; i < panels - 1; i++) { for (int i = 0; i < items - 1; i++) {
Panel* panel = (Panel*) Vector_get(this->panels, i); Panel* panel = (Panel*) Vector_get(this->items, i);
Panel_resize(panel, panel->w, LINES-y1+y2); Panel_resize(panel, panel->w, LINES-y1+y2);
Panel_move(panel, lastX, y1); Panel_move(panel, lastX, y1);
lastX = panel->x + panel->w + 1; lastX = panel->x + panel->w + 1;
} }
Panel* panel = (Panel*) Vector_get(this->panels, panels-1); Panel* panel = (Panel*) Vector_get(this->items, items-1);
Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2); Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
Panel_move(panel, lastX, y1); Panel_move(panel, lastX, y1);
} }
@ -127,29 +120,17 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
bool quit = false; bool quit = false;
int focus = 0; int focus = 0;
Panel* panelFocus = (Panel*) Vector_get(this->panels, focus); Panel* panelFocus = (Panel*) Vector_get(this->items, focus);
if (this->fuBar) if (this->fuBar)
FunctionBar_draw(this->fuBar, NULL); FunctionBar_draw(this->fuBar, NULL);
this->lastScan = 0;
int ch = 0; int ch = 0;
while (!quit) { while (!quit) {
int panels = this->panelCount; int items = this->itemCount;
if (this->header) { for (int i = 0; i < items; i++) {
time_t now = time(NULL); Panel* panel = (Panel*) Vector_get(this->items, i);
if (now > this->lastScan) {
ProcessList_scan(this->header->pl);
ProcessList_sort(this->header->pl);
this->lastScan = now;
}
Header_draw(this->header);
ProcessList_rebuildPanel(this->header->pl, false, false, false, false, NULL);
}
for (int i = 0; i < panels; i++) {
Panel* panel = (Panel*) Vector_get(this->panels, i);
Panel_draw(panel, i == focus); Panel_draw(panel, i == focus);
if (i < panels) { if (i < items) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1); mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
} }
@ -170,11 +151,10 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
if (mevent.y == LINES - 1) { if (mevent.y == LINES - 1) {
ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x); ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x);
} else { } else {
for (int i = 0; i < this->panelCount; i++) { for (int i = 0; i < this->itemCount; i++) {
Panel* panel = (Panel*) Vector_get(this->panels, i); Panel* panel = (Panel*) Vector_get(this->items, i);
if (mevent.x > panel->x && mevent.x <= panel->x+panel->w && if (mevent.x > panel->x && mevent.x <= panel->x+panel->w &&
mevent.y > panel->y && mevent.y <= panel->y+panel->h && mevent.y > panel->y && mevent.y <= panel->y+panel->h) {
(this->allowFocusChange || panelFocus == panel) ) {
focus = i; focus = i;
panelFocus = panel; panelFocus = panel;
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
@ -185,8 +165,8 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
} }
} }
if (Panel_eventHandlerFn(panelFocus)) { if (panelFocus->eventHandler) {
HandlerResult result = Panel_eventHandler(panelFocus, ch); HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
if (result == HANDLED) { if (result == HANDLED) {
continue; continue;
} else if (result == BREAK_LOOP) { } else if (result == BREAK_LOOP) {
@ -204,26 +184,20 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
continue; continue;
} }
case KEY_LEFT: case KEY_LEFT:
case KEY_CTRLB:
if (!this->allowFocusChange)
break;
tryLeft: tryLeft:
if (focus > 0) if (focus > 0)
focus--; focus--;
panelFocus = (Panel*) Vector_get(this->panels, focus); panelFocus = (Panel*) Vector_get(this->items, focus);
if (Panel_size(panelFocus) == 0 && focus > 0) if (Panel_getSize(panelFocus) == 0 && focus > 0)
goto tryLeft; goto tryLeft;
break; break;
case KEY_RIGHT: case KEY_RIGHT:
case KEY_CTRLF:
case 9: case 9:
if (!this->allowFocusChange)
break;
tryRight: tryRight:
if (focus < this->panelCount - 1) if (focus < this->itemCount - 1)
focus++; focus++;
panelFocus = (Panel*) Vector_get(this->panels, focus); panelFocus = (Panel*) Vector_get(this->items, focus);
if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1) if (Panel_getSize(panelFocus) == 0 && focus < this->itemCount - 1)
goto tryRight; goto tryRight;
break; break;
case KEY_F(10): case KEY_F(10):

View File

@ -3,15 +3,22 @@
#ifndef HEADER_ScreenManager #ifndef HEADER_ScreenManager
#define HEADER_ScreenManager #define HEADER_ScreenManager
/* /*
htop - ScreenManager.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "FunctionBar.h" #include "Panel.h"
#include "Object.h"
#include "Vector.h" #include "Vector.h"
#include "Header.h" #include "FunctionBar.h"
#include "debug.h"
#include <assert.h>
#include <stdbool.h>
typedef enum Orientation_ { typedef enum Orientation_ {
VERTICAL, VERTICAL,
@ -24,18 +31,15 @@ typedef struct ScreenManager_ {
int x2; int x2;
int y2; int y2;
Orientation orientation; Orientation orientation;
Vector* panels; Vector* items;
Vector* fuBars; Vector* fuBars;
int panelCount; int itemCount;
const FunctionBar* fuBar; FunctionBar* fuBar;
const Header* header;
time_t lastScan;
bool owner; bool owner;
bool allowFocusChange;
} ScreenManager; } ScreenManager;
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, bool owner); ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, bool owner);
void ScreenManager_delete(ScreenManager* this); void ScreenManager_delete(ScreenManager* this);
@ -43,7 +47,7 @@ extern int ScreenManager_size(ScreenManager* this);
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size); void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size);
Panel* ScreenManager_remove(ScreenManager* this, int idx); Panel* ScreenManager_remove(ScreenManager* this, int index);
void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2); void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2);

View File

@ -1,34 +1,28 @@
/* /*
htop - Settings.c htop - Settings.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Settings.h" #include "Settings.h"
#include "String.h" #include "String.h"
#include "Vector.h" #include "ProcessList.h"
#include "Header.h"
#include <sys/stat.h> #include "debug.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_DELAY 15 #define DEFAULT_DELAY 15
/*{ /*{
#include "ProcessList.h"
#include "Header.h"
#include <stdbool.h>
typedef struct Settings_ { typedef struct Settings_ {
char* userSettings; char* userSettings;
ProcessList* pl; ProcessList* pl;
Header* header; Header* header;
int colorScheme; int colorScheme;
int delay;
bool changed; bool changed;
int delay;
} Settings; } Settings;
}*/ }*/
@ -40,10 +34,10 @@ void Settings_delete(Settings* this) {
static void Settings_readMeters(Settings* this, char* line, HeaderSide side) { static void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; char** ids = String_split(trim, ' ');
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
for (int i = 0; ids[i]; i++) { int i;
for (i = 0; ids[i] != NULL; i++) {
Header_createMeter(this->header, ids[i], side); Header_createMeter(this->header, ids[i], side);
} }
String_freeArray(ids); String_freeArray(ids);
@ -51,44 +45,41 @@ static void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) { static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; char** ids = String_split(trim, ' ');
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
for (int i = 0; ids[i]; i++) { int i;
for (i = 0; ids[i] != NULL; i++) {
int mode = atoi(ids[i]); int mode = atoi(ids[i]);
Header_setMode(this->header, i, mode, side); Header_setMode(this->header, i, mode, side);
} }
String_freeArray(ids); String_freeArray(ids);
} }
static bool Settings_read(Settings* this, const char* fileName, int cpuCount) { static bool Settings_read(Settings* this, char* fileName) {
FILE* fd = fopen(fileName, "r"); // TODO: implement File object and make
if (!fd) // file I/O object-oriented.
FILE* fd;
fd = fopen(fileName, "r");
if (fd == NULL) {
return false; return false;
}
const int maxLine = 2048; const int maxLine = 65535;
char buffer[maxLine]; char buffer[maxLine];
bool readMeters = false; bool readMeters = false;
while (fgets(buffer, maxLine, fd)) { while (!feof(fd)) {
int nOptions; buffer[0] = '\0';
char** option = String_split(buffer, '=', &nOptions); fgets(buffer, maxLine, fd);
if (nOptions < 2) { char** option = String_split(buffer, '=');
String_freeArray(option);
continue;
}
if (String_eq(option[0], "fields")) { if (String_eq(option[0], "fields")) {
char* trim = String_trim(option[1]); char* trim = String_trim(option[1]);
int nIds; char** ids = String_split(trim, ' ');
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
int i, j; int i, j;
this->pl->flags = 0; for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i] != NULL; i++) {
for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i]; i++) {
// This "+1" is for compatibility with the older enum format. // This "+1" is for compatibility with the older enum format.
int id = atoi(ids[i]) + 1; int id = atoi(ids[i]) + 1;
if (id > 0 && id < LAST_PROCESSFIELD) { if (id > 0 && id < LAST_PROCESSFIELD) {
this->pl->fields[j] = id; this->pl->fields[j] = id;
this->pl->flags |= Process_fieldFlags[id];
j++; j++;
} }
} }
@ -109,8 +100,6 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
this->pl->hideUserlandThreads = atoi(option[1]); this->pl->hideUserlandThreads = atoi(option[1]);
} else if (String_eq(option[0], "shadow_other_users")) { } else if (String_eq(option[0], "shadow_other_users")) {
this->pl->shadowOtherUsers = atoi(option[1]); this->pl->shadowOtherUsers = atoi(option[1]);
} else if (String_eq(option[0], "show_thread_names")) {
this->pl->showThreadNames = atoi(option[1]);
} else if (String_eq(option[0], "highlight_base_name")) { } else if (String_eq(option[0], "highlight_base_name")) {
this->pl->highlightBaseName = atoi(option[1]); this->pl->highlightBaseName = atoi(option[1]);
} else if (String_eq(option[0], "highlight_megabytes")) { } else if (String_eq(option[0], "highlight_megabytes")) {
@ -124,12 +113,6 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
this->pl->detailedCPUTime = atoi(option[1]); this->pl->detailedCPUTime = atoi(option[1]);
} else if (String_eq(option[0], "detailed_cpu_time")) { } else if (String_eq(option[0], "detailed_cpu_time")) {
this->pl->detailedCPUTime = atoi(option[1]); this->pl->detailedCPUTime = atoi(option[1]);
} else if (String_eq(option[0], "cpu_count_from_zero")) {
this->pl->countCPUsFromZero = atoi(option[1]);
} else if (String_eq(option[0], "update_process_names")) {
this->pl->updateProcessNames = atoi(option[1]);
} else if (String_eq(option[0], "account_guest_in_cpu_meter")) {
this->pl->accountGuestInCPUMeter = atoi(option[1]);
} else if (String_eq(option[0], "delay")) { } else if (String_eq(option[0], "delay")) {
this->delay = atoi(option[1]); this->delay = atoi(option[1]);
} else if (String_eq(option[0], "color_scheme")) { } else if (String_eq(option[0], "color_scheme")) {
@ -153,7 +136,7 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
} }
fclose(fd); fclose(fd);
if (!readMeters) { if (!readMeters) {
Header_defaultMeters(this->header, cpuCount); Header_defaultMeters(this->header);
} }
return true; return true;
} }
@ -166,8 +149,9 @@ bool Settings_write(Settings* this) {
if (fd == NULL) { if (fd == NULL) {
return false; return false;
} }
fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n"); fprintf(fd, "# Beware! This file is rewritten every time htop exits.\n");
fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n"); fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n");
fprintf(fd, "# (I know, it's in the todo list).\n");
fprintf(fd, "fields="); fprintf(fd, "fields=");
for (int i = 0; this->pl->fields[i]; i++) { for (int i = 0; this->pl->fields[i]; i++) {
// This "-1" is for compatibility with the older enum format. // This "-1" is for compatibility with the older enum format.
@ -181,16 +165,12 @@ bool Settings_write(Settings* this) {
fprintf(fd, "hide_kernel_threads=%d\n", (int) this->pl->hideKernelThreads); fprintf(fd, "hide_kernel_threads=%d\n", (int) this->pl->hideKernelThreads);
fprintf(fd, "hide_userland_threads=%d\n", (int) this->pl->hideUserlandThreads); fprintf(fd, "hide_userland_threads=%d\n", (int) this->pl->hideUserlandThreads);
fprintf(fd, "shadow_other_users=%d\n", (int) this->pl->shadowOtherUsers); fprintf(fd, "shadow_other_users=%d\n", (int) this->pl->shadowOtherUsers);
fprintf(fd, "show_thread_names=%d\n", (int) this->pl->showThreadNames);
fprintf(fd, "highlight_base_name=%d\n", (int) this->pl->highlightBaseName); fprintf(fd, "highlight_base_name=%d\n", (int) this->pl->highlightBaseName);
fprintf(fd, "highlight_megabytes=%d\n", (int) this->pl->highlightMegabytes); fprintf(fd, "highlight_megabytes=%d\n", (int) this->pl->highlightMegabytes);
fprintf(fd, "highlight_threads=%d\n", (int) this->pl->highlightThreads); fprintf(fd, "highlight_threads=%d\n", (int) this->pl->highlightThreads);
fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView); fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView);
fprintf(fd, "header_margin=%d\n", (int) this->header->margin); fprintf(fd, "header_margin=%d\n", (int) this->header->margin);
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->pl->detailedCPUTime); fprintf(fd, "detailed_cpu_time=%d\n", (int) this->pl->detailedCPUTime);
fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->pl->countCPUsFromZero);
fprintf(fd, "update_process_names=%d\n", (int) this->pl->updateProcessNames);
fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->pl->accountGuestInCPUMeter);
fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme); fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
fprintf(fd, "delay=%d\n", (int) this->delay); fprintf(fd, "delay=%d\n", (int) this->delay);
fprintf(fd, "left_meters="); fprintf(fd, "left_meters=");
@ -219,66 +199,36 @@ bool Settings_write(Settings* this) {
return true; return true;
} }
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) { Settings* Settings_new(ProcessList* pl, Header* header) {
Settings* this = malloc(sizeof(Settings)); Settings* this = malloc(sizeof(Settings));
this->pl = pl; this->pl = pl;
this->header = header; this->header = header;
char* legacyDotfile = NULL; char* home;
char* rcfile = getenv("HTOPRC"); char* rcfile;
if (rcfile) { home = getenv("HOME_ETC");
this->userSettings = strdup(rcfile); if (!home) home = getenv("HOME");
} else {
const char* home = getenv("HOME");
if (!home) home = ""; if (!home) home = "";
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); rcfile = getenv("HOMERC");
char* configDir = NULL; if (!rcfile)
char* htopDir = NULL; this->userSettings = String_cat(home, "/.htoprc");
if (xdgConfigHome) { else
this->userSettings = String_cat(xdgConfigHome, "/htop/htoprc"); this->userSettings = String_copy(rcfile);
configDir = strdup(xdgConfigHome);
htopDir = String_cat(xdgConfigHome, "/htop");
} else {
this->userSettings = String_cat(home, "/.config/htop/htoprc");
configDir = String_cat(home, "/.config");
htopDir = String_cat(home, "/.config/htop");
}
legacyDotfile = String_cat(home, "/.htoprc");
(void) mkdir(configDir, 0700);
(void) mkdir(htopDir, 0700);
free(htopDir);
free(configDir);
struct stat st;
if (lstat(legacyDotfile, &st) != 0) {
st.st_mode = 0;
}
if (access(legacyDotfile, R_OK) != 0 || S_ISLNK(st.st_mode)) {
free(legacyDotfile);
legacyDotfile = NULL;
}
}
this->colorScheme = 0; this->colorScheme = 0;
this->changed = false; this->changed = false;
this->delay = DEFAULT_DELAY; this->delay = DEFAULT_DELAY;
bool ok = Settings_read(this, legacyDotfile ? legacyDotfile : this->userSettings, cpuCount); bool ok = Settings_read(this, this->userSettings);
if (ok) { if (!ok) {
if (legacyDotfile) {
// Transition to new location and delete old configuration file
if (Settings_write(this))
unlink(legacyDotfile);
}
} else {
this->changed = true; this->changed = true;
// TODO: how to get SYSCONFDIR correctly through Autoconf? // TODO: how to get SYSCONFDIR correctly through Autoconf?
char* systemSettings = String_cat(SYSCONFDIR, "/htoprc"); char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
ok = Settings_read(this, systemSettings, cpuCount); ok = Settings_read(this, systemSettings);
free(systemSettings); free(systemSettings);
if (!ok) { if (!ok) {
Header_defaultMeters(this->header, cpuCount); Header_defaultMeters(this->header);
pl->hideKernelThreads = true; pl->hideKernelThreads = true;
pl->highlightMegabytes = true; pl->highlightMegabytes = true;
pl->highlightThreads = false; pl->highlightThreads = false;
} }
} }
free(legacyDotfile);
return this; return this;
} }

View File

@ -4,24 +4,27 @@
#define HEADER_Settings #define HEADER_Settings
/* /*
htop - Settings.h htop - Settings.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define DEFAULT_DELAY 15 #include "String.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "Header.h" #include "Header.h"
#include <stdbool.h>
#include "debug.h"
#define DEFAULT_DELAY 15
typedef struct Settings_ { typedef struct Settings_ {
char* userSettings; char* userSettings;
ProcessList* pl; ProcessList* pl;
Header* header; Header* header;
int colorScheme; int colorScheme;
int delay;
bool changed; bool changed;
int delay;
} Settings; } Settings;
@ -29,6 +32,6 @@ void Settings_delete(Settings* this);
bool Settings_write(Settings* this); bool Settings_write(Settings* this);
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount); Settings* Settings_new(ProcessList* pl, Header* header);
#endif #endif

101
SignalItem.c Normal file
View File

@ -0,0 +1,101 @@
/*
htop - SignalItem.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "SignalItem.h"
#include "String.h"
#include "Object.h"
#include "RichString.h"
#include <string.h>
#include "debug.h"
#define SIGNAL_COUNT 34
/*{
typedef struct Signal_ {
Object super;
char* name;
int number;
} Signal;
}*/
#ifdef DEBUG
char* SIGNAL_CLASS = "Signal";
#else
#define SIGNAL_CLASS NULL
#endif
static void Signal_delete(Object* cast) {
Signal* this = (Signal*)cast;
assert (this != NULL);
// names are string constants, so we're not deleting them.
free(this);
}
static void Signal_display(Object* cast, RichString* out) {
Signal* this = (Signal*)cast;
assert (this != NULL);
char buffer[31];
snprintf(buffer, 30, "%2d %s", this->number, this->name);
RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer);
}
static Signal* Signal_new(char* name, int number) {
Signal* this = malloc(sizeof(Signal));
Object_setClass(this, SIGNAL_CLASS);
((Object*)this)->display = Signal_display;
((Object*)this)->delete = Signal_delete;
this->name = name;
this->number = number;
return this;
}
int Signal_getSignalCount() {
return SIGNAL_COUNT;
}
Signal** Signal_getSignalTable() {
Signal** signals = malloc(sizeof(Signal*) * SIGNAL_COUNT);
signals[0] = Signal_new("Cancel", 0);
signals[1] = Signal_new("SIGHUP", 1);
signals[2] = Signal_new("SIGINT", 2);
signals[3] = Signal_new("SIGQUIT", 3);
signals[4] = Signal_new("SIGILL", 4);
signals[5] = Signal_new("SIGTRAP", 5);
signals[6] = Signal_new("SIGABRT", 6);
signals[7] = Signal_new("SIGIOT", 6);
signals[8] = Signal_new("SIGBUS", 7);
signals[9] = Signal_new("SIGFPE", 8);
signals[10] = Signal_new("SIGKILL", 9);
signals[11] = Signal_new("SIGUSR1", 10);
signals[12] = Signal_new("SIGSEGV", 11);
signals[13] = Signal_new("SIGUSR2", 12);
signals[14] = Signal_new("SIGPIPE", 13);
signals[15] = Signal_new("SIGALRM", 14);
signals[16] = Signal_new("SIGTERM", 15);
signals[17] = Signal_new("SIGSTKFLT", 16);
signals[18] = Signal_new("SIGCHLD", 17);
signals[19] = Signal_new("SIGCONT", 18);
signals[20] = Signal_new("SIGSTOP", 19);
signals[21] = Signal_new("SIGTSTP", 20);
signals[22] = Signal_new("SIGTTIN", 21);
signals[23] = Signal_new("SIGTTOU", 22);
signals[24] = Signal_new("SIGURG", 23);
signals[25] = Signal_new("SIGXCPU", 24);
signals[26] = Signal_new("SIGXFSZ", 25);
signals[27] = Signal_new("SIGVTALRM", 26);
signals[28] = Signal_new("SIGPROF", 27);
signals[29] = Signal_new("SIGWINCH", 28);
signals[30] = Signal_new("SIGIO", 29);
signals[31] = Signal_new("SIGPOLL", 29);
signals[32] = Signal_new("SIGPWR", 30);
signals[33] = Signal_new("SIGSYS", 31);
return signals;
}

39
SignalItem.h Normal file
View File

@ -0,0 +1,39 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_SignalItem
#define HEADER_SignalItem
/*
htop - SignalItem.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "String.h"
#include "Object.h"
#include "RichString.h"
#include <string.h>
#include "debug.h"
#define SIGNAL_COUNT 34
typedef struct Signal_ {
Object super;
char* name;
int number;
} Signal;
#ifdef DEBUG
extern char* SIGNAL_CLASS;
#else
#define SIGNAL_CLASS NULL
#endif
int Signal_getSignalCount();
Signal** Signal_getSignalTable();
#endif

View File

@ -1,72 +1,77 @@
/*
htop - SignalsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "SignalsPanel.h" #include "SignalsPanel.h"
#include "Panel.h"
#include "ListItem.h" #include "SignalItem.h"
#include "RichString.h" #include "RichString.h"
#include <stdlib.h> #include "debug.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
/*{ /*{
typedef struct SignalItem_ { typedef struct SignalsPanel_ {
const char* name; Panel super;
int number;
} SignalItem; int state;
Signal** signals;
} SignalsPanel;
}*/ }*/
static SignalItem signals[] = { static HandlerResult SignalsPanel_eventHandler(Panel* super, int ch) {
{ .name = " 0 Cancel", .number = 0 }, SignalsPanel* this = (SignalsPanel*) super;
{ .name = " 1 SIGHUP", .number = 1 },
{ .name = " 2 SIGINT", .number = 2 },
{ .name = " 3 SIGQUIT", .number = 3 },
{ .name = " 4 SIGILL", .number = 4 },
{ .name = " 5 SIGTRAP", .number = 5 },
{ .name = " 6 SIGABRT", .number = 6 },
{ .name = " 6 SIGIOT", .number = 6 },
{ .name = " 7 SIGBUS", .number = 7 },
{ .name = " 8 SIGFPE", .number = 8 },
{ .name = " 9 SIGKILL", .number = 9 },
{ .name = "10 SIGUSR1", .number = 10 },
{ .name = "11 SIGSEGV", .number = 11 },
{ .name = "12 SIGUSR2", .number = 12 },
{ .name = "13 SIGPIPE", .number = 13 },
{ .name = "14 SIGALRM", .number = 14 },
{ .name = "15 SIGTERM", .number = 15 },
{ .name = "16 SIGSTKFLT", .number = 16 },
{ .name = "17 SIGCHLD", .number = 17 },
{ .name = "18 SIGCONT", .number = 18 },
{ .name = "19 SIGSTOP", .number = 19 },
{ .name = "20 SIGTSTP", .number = 20 },
{ .name = "21 SIGTTIN", .number = 21 },
{ .name = "22 SIGTTOU", .number = 22 },
{ .name = "23 SIGURG", .number = 23 },
{ .name = "24 SIGXCPU", .number = 24 },
{ .name = "25 SIGXFSZ", .number = 25 },
{ .name = "26 SIGVTALRM", .number = 26 },
{ .name = "27 SIGPROF", .number = 27 },
{ .name = "28 SIGWINCH", .number = 28 },
{ .name = "29 SIGIO", .number = 29 },
{ .name = "29 SIGPOLL", .number = 29 },
{ .name = "30 SIGPWR", .number = 30 },
{ .name = "31 SIGSYS", .number = 31 },
};
Panel* SignalsPanel_new() { int size = Panel_getSize(super);
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem));
for(unsigned int i = 0; i < sizeof(signals)/sizeof(SignalItem); i++) if (ch <= 255 && isdigit(ch)) {
Panel_set(this, i, (Object*) ListItem_new(signals[i].name, signals[i].number)); int signal = ch-48 + this->state;
Panel_setHeader(this, "Send signal:"); for (int i = 0; i < size; i++)
Panel_setSelected(this, 16); // 16th item is SIGTERM if (((Signal*) Panel_get(super, i))->number == signal) {
Panel_setSelected(super, i);
break;
}
this->state = signal * 10;
if (this->state > 100)
this->state = 0;
return HANDLED;
} else {
this->state = 0;
}
if (ch == 13) {
return BREAK_LOOP;
}
return IGNORED;
}
static void SignalsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
SignalsPanel* this = (SignalsPanel*) object;
Panel_done(super);
free(this->signals);
free(this);
}
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h) {
SignalsPanel* this = (SignalsPanel*) malloc(sizeof(SignalsPanel));
Panel* super = (Panel*) this;
Panel_init(super, x, y, w, h, SIGNAL_CLASS, true);
((Object*)this)->delete = SignalsPanel_delete;
this->signals = Signal_getSignalTable();
super->eventHandler = SignalsPanel_eventHandler;
int sigCount = Signal_getSignalCount();
for(int i = 0; i < sigCount; i++)
Panel_set(super, i, (Object*) this->signals[i]);
SignalsPanel_reset(this);
return this; return this;
} }
void SignalsPanel_reset(SignalsPanel* this) {
Panel* super = (Panel*) this;
Panel_setHeader(super, "Send signal:");
Panel_setSelected(super, 16); // 16th item is SIGTERM
this->state = 0;
}

View File

@ -2,20 +2,27 @@
#ifndef HEADER_SignalsPanel #ifndef HEADER_SignalsPanel
#define HEADER_SignalsPanel #define HEADER_SignalsPanel
/*
htop - SignalsPanel.h #include "Panel.h"
(C) 2004-2011 Hisham H. Muhammad #include "SignalItem.h"
Released under the GNU GPL, see the COPYING file #include "RichString.h"
in the source distribution for its full text.
*/ #include "debug.h"
#include <assert.h>
#include <ctype.h>
typedef struct SignalItem_ { typedef struct SignalsPanel_ {
const char* name; Panel super;
int number;
} SignalItem; int state;
Signal** signals;
} SignalsPanel;
Panel* SignalsPanel_new(); SignalsPanel* SignalsPanel_new(int x, int y, int w, int h);
void SignalsPanel_reset(SignalsPanel* this);
#endif #endif

View File

@ -1,25 +1,28 @@
/* /*
htop - String.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE
#include "String.h" #include "String.h"
#include "config.h"
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "debug.h"
/*{ /*{
#define String_startsWith(s, match) (strstr((s), (match)) == (s)) #define String_startsWith(s, match) (strstr((s), (match)) == (s))
#define String_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
}*/ }*/
char* String_cat(const char* s1, const char* s2) { inline char* String_copy(char* orig) {
return strdup(orig);
}
char* String_cat(char* s1, char* s2) {
int l1 = strlen(s1); int l1 = strlen(s1);
int l2 = strlen(s2); int l2 = strlen(s2);
char* out = malloc(l1 + l2 + 1); char* out = malloc(l1 + l2 + 1);
@ -28,7 +31,7 @@ char* String_cat(const char* s1, const char* s2) {
return out; return out;
} }
char* String_trim(const char* in) { char* String_trim(char* in) {
while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') { while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') {
in++; in++;
} }
@ -52,8 +55,7 @@ inline int String_eq(const char* s1, const char* s2) {
return (strcmp(s1, s2) == 0); return (strcmp(s1, s2) == 0);
} }
char** String_split(const char* s, char sep, int* n) { char** String_split(char* s, char sep) {
*n = 0;
const int rate = 10; const int rate = 10;
char** out = (char**) malloc(sizeof(char*) * rate); char** out = (char**) malloc(sizeof(char*) * rate);
int ctr = 0; int ctr = 0;
@ -68,13 +70,7 @@ char** String_split(const char* s, char sep, int* n) {
ctr++; ctr++;
if (ctr == blocks) { if (ctr == blocks) {
blocks += rate; blocks += rate;
char** newOut = (char**) realloc(out, sizeof(char*) * blocks); out = (char**) realloc(out, sizeof(char*) * blocks);
if (newOut) {
out = newOut;
} else {
blocks -= rate;
break;
}
} }
s += size + 1; s += size + 1;
} }
@ -85,12 +81,8 @@ char** String_split(const char* s, char sep, int* n) {
out[ctr] = token; out[ctr] = token;
ctr++; ctr++;
} }
char** newOut = realloc(out, sizeof(char*) * (ctr + 1)); out = realloc(out, sizeof(char*) * (ctr + 1));
if (newOut) {
out = newOut;
}
out[ctr] = NULL; out[ctr] = NULL;
*n = ctr;
return out; return out;
} }
@ -101,29 +93,13 @@ void String_freeArray(char** s) {
free(s); free(s);
} }
char* String_getToken(const char* line, const unsigned short int numMatch) { int String_contains_i(char* s, char* match) {
const unsigned short int len = strlen(line); int lens = strlen(s);
char inWord = 0; int lenmatch = strlen(match);
unsigned short int count = 0; for (int i = 0; i < lens-lenmatch; i++) {
char match[50]; if (strncasecmp(s, match, strlen(match)) == 0)
return 1;
unsigned short int foundCount = 0; s++;
for (unsigned short int i = 0; i < len; i++) {
char lastState = inWord;
inWord = line[i] == ' ' ? 0:1;
if (lastState == 0 && inWord == 1)
count++;
if(inWord == 1){
if (count == numMatch && line[i] != ' ' && line[i] != '\0' && line[i] != '\n' && line[i] != (char)EOF) {
match[foundCount] = line[i];
foundCount++;
} }
} return 0;
}
match[foundCount] = '\0';
return((char*)strdup(match));
} }

View File

@ -3,25 +3,34 @@
#ifndef HEADER_String #ifndef HEADER_String
#define HEADER_String #define HEADER_String
/* /*
htop - String.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include "debug.h"
#define String_startsWith(s, match) (strstr((s), (match)) == (s)) #define String_startsWith(s, match) (strstr((s), (match)) == (s))
#define String_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
char* String_cat(const char* s1, const char* s2); extern char* String_copy(char* orig);
char* String_trim(const char* in); char* String_cat(char* s1, char* s2);
char* String_trim(char* in);
extern int String_eq(const char* s1, const char* s2); extern int String_eq(const char* s1, const char* s2);
char** String_split(const char* s, char sep, int* n); char** String_split(char* s, char sep);
void String_freeArray(char** s); void String_freeArray(char** s);
char* String_getToken(const char* line, const unsigned short int numMatch); int String_contains_i(char* s, char* match);
#endif #endif

View File

@ -1,67 +1,53 @@
/* /*
htop - SwapMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "SwapMeter.h" #include "SwapMeter.h"
#include "Meter.h"
#include "CRT.h"
#include "ProcessList.h" #include "ProcessList.h"
#include <stdlib.h> #include <stdlib.h>
#include <curses.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <sys/param.h> #include <sys/param.h>
#include "debug.h"
#include <assert.h> #include <assert.h>
/*{
#include "Meter.h"
}*/
#define KILOBYTE 1
#define MEGABYTE 1024
#define GIGABYTE 1048576
int SwapMeter_attributes[] = { int SwapMeter_attributes[] = {
SWAP SWAP
}; };
/* NOTE: Value is in kilobytes */
static void SwapMeter_humanNumber(char* buffer, const long int* value) {
sprintf(buffer, "%ldM ", *value / MEGABYTE);
}
static void SwapMeter_setValues(Meter* this, char* buffer, int len) { static void SwapMeter_setValues(Meter* this, char* buffer, int len) {
long int usedSwap = this->pl->usedSwap; long int usedSwap = this->pl->usedSwap;
this->total = this->pl->totalSwap; this->total = this->pl->totalSwap;
this->values[0] = usedSwap; this->values[0] = usedSwap;
snprintf(buffer, len, "%ld/%ldMB", (long int) usedSwap / 1024, (long int) this->total / 1024);
snprintf(buffer, len, "%ld/%ldMB", (long int) usedSwap / MEGABYTE, (long int) this->total / MEGABYTE);
} }
static void SwapMeter_display(Object* cast, RichString* out) { static void SwapMeter_display(Object* cast, RichString* out) {
char buffer[50]; char buffer[50];
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
long int swap = (long int) this->values[0]; long int swap = (long int) this->values[0];
long int total = (long int) this->total; RichString_init(out);
RichString_write(out, CRT_colors[METER_TEXT], ":"); RichString_append(out, CRT_colors[METER_TEXT], ":");
SwapMeter_humanNumber(buffer, &total); sprintf(buffer, "%ldM ", (long int) this->total / 1024);
RichString_append(out, CRT_colors[METER_VALUE], buffer); RichString_append(out, CRT_colors[METER_VALUE], buffer);
SwapMeter_humanNumber(buffer, &swap); sprintf(buffer, "%ldk", swap);
RichString_append(out, CRT_colors[METER_TEXT], "used:"); RichString_append(out, CRT_colors[METER_TEXT], "used:");
RichString_append(out, CRT_colors[METER_VALUE], buffer); RichString_append(out, CRT_colors[METER_VALUE], buffer);
} }
MeterClass SwapMeter_class = { MeterType SwapMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = SwapMeter_display,
},
.setValues = SwapMeter_setValues, .setValues = SwapMeter_setValues,
.defaultMode = BAR_METERMODE, .display = SwapMeter_display,
.mode = BAR_METERMODE,
.items = 1,
.total = 100.0, .total = 100.0,
.attributes = SwapMeter_attributes, .attributes = SwapMeter_attributes,
.name = "Swap", .name = "Swap",

View File

@ -3,21 +3,27 @@
#ifndef HEADER_SwapMeter #ifndef HEADER_SwapMeter
#define HEADER_SwapMeter #define HEADER_SwapMeter
/* /*
htop - SwapMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#define KILOBYTE 1 #include "ProcessList.h"
#define MEGABYTE 1024
#define GIGABYTE 1048576 #include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include <sys/param.h>
#include "debug.h"
#include <assert.h>
extern int SwapMeter_attributes[]; extern int SwapMeter_attributes[];
/* NOTE: Value is in kilobytes */ extern MeterType SwapMeter;
extern MeterClass SwapMeter_class;
#endif #endif

20
TODO Normal file
View File

@ -0,0 +1,20 @@
BUGS:
* tagged files are cleared if 'kill' fails
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=375219
* add swap column for swap usage in MB
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=365038
* Filter out nonprintable characters in command lines
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=419140
FEATURES:
* expand/collapse on tree
* handle saving of .htoprc more elegantly
* make bars display refresh independent from list refresh
* auto-calibrate delay
* add some more 'top' features
* add more command-line parameters
* show 'process view'
* make keybindings configurable, blah blah blah...

View File

@ -1,68 +1,46 @@
/* /*
htop - TasksMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "TasksMeter.h" #include "TasksMeter.h"
#include "Meter.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "CRT.h" #include "CRT.h"
/*{ #include "debug.h"
#include "Meter.h"
}*/
int TasksMeter_attributes[] = { int TasksMeter_attributes[] = {
TASKS_RUNNING TASKS_RUNNING
}; };
static void TasksMeter_setValues(Meter* this, char* buffer, int len) { static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
ProcessList* pl = this->pl; this->total = this->pl->totalTasks;
this->total = pl->totalTasks; this->values[0] = this->pl->runningTasks;
this->values[0] = pl->runningTasks;
snprintf(buffer, len, "%d/%d", (int) this->values[0], (int) this->total); snprintf(buffer, len, "%d/%d", (int) this->values[0], (int) this->total);
} }
static void TasksMeter_display(Object* cast, RichString* out) { static void TasksMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
ProcessList* pl = this->pl; RichString_init(out);
char buffer[20]; char buffer[20];
sprintf(buffer, "%d", (int)(this->total - pl->userlandThreads - pl->kernelThreads)); sprintf(buffer, "%d", (int)this->total);
RichString_write(out, CRT_colors[METER_VALUE], buffer); RichString_append(out, CRT_colors[METER_VALUE], buffer);
int threadValueColor = CRT_colors[METER_VALUE]; RichString_append(out, CRT_colors[METER_TEXT], " total, ");
int threadCaptionColor = CRT_colors[METER_TEXT];
if (pl->highlightThreads) {
threadValueColor = CRT_colors[PROCESS_THREAD_BASENAME];
threadCaptionColor = CRT_colors[PROCESS_THREAD];
}
if (!pl->hideUserlandThreads) {
RichString_append(out, CRT_colors[METER_TEXT], ", ");
sprintf(buffer, "%d", (int)pl->userlandThreads);
RichString_append(out, threadValueColor, buffer);
RichString_append(out, threadCaptionColor, " thr");
}
if (!pl->hideKernelThreads) {
RichString_append(out, CRT_colors[METER_TEXT], ", ");
sprintf(buffer, "%d", (int)pl->kernelThreads);
RichString_append(out, threadValueColor, buffer);
RichString_append(out, threadCaptionColor, " kthr");
}
RichString_append(out, CRT_colors[METER_TEXT], "; ");
sprintf(buffer, "%d", (int)this->values[0]); sprintf(buffer, "%d", (int)this->values[0]);
RichString_append(out, CRT_colors[TASKS_RUNNING], buffer); RichString_append(out, CRT_colors[TASKS_RUNNING], buffer);
RichString_append(out, CRT_colors[METER_TEXT], " running"); RichString_append(out, CRT_colors[METER_TEXT], " running");
} }
MeterClass TasksMeter_class = { MeterType TasksMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = TasksMeter_display,
},
.setValues = TasksMeter_setValues, .setValues = TasksMeter_setValues,
.defaultMode = TEXT_METERMODE, .display = TasksMeter_display,
.mode = TEXT_METERMODE,
.items = 1,
.total = 100.0, .total = 100.0,
.attributes = TasksMeter_attributes, .attributes = TasksMeter_attributes,
.name = "Tasks", .name = "Tasks",

View File

@ -3,16 +3,22 @@
#ifndef HEADER_TasksMeter #ifndef HEADER_TasksMeter
#define HEADER_TasksMeter #define HEADER_TasksMeter
/* /*
htop - TasksMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include "ProcessList.h"
#include "CRT.h"
#include "debug.h"
extern int TasksMeter_attributes[]; extern int TasksMeter_attributes[];
extern MeterClass TasksMeter_class; extern MeterType TasksMeter;
#endif #endif

View File

@ -5,76 +5,60 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "TraceScreen.h" #define _GNU_SOURCE
#include "CRT.h"
#include "ProcessList.h"
#include "ListItem.h"
#include "IncSet.h"
#include "String.h"
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h>
/*{ #include "TraceScreen.h"
#include "ProcessList.h"
#include "Process.h" #include "Process.h"
#include "ListItem.h"
#include "Panel.h" #include "Panel.h"
#include "FunctionBar.h" #include "FunctionBar.h"
/*{
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; Process* process;
Panel* display; Panel* display;
FunctionBar* bar;
bool tracing; bool tracing;
} TraceScreen; } TraceScreen;
}*/ }*/
static const char* tsFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL}; static char* tbFunctions[3] = {"AutoScroll ", "Stop Tracing ", "Done "};
static const char* tsKeys[] = {"F3", "F4", "F8", "F9", "Esc"}; static char* tbKeys[3] = {"F4", "F5", "Esc"};
static int tsEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27}; static int tbEvents[3] = {KEY_F(4), KEY_F(5), 27};
TraceScreen* TraceScreen_new(Process* process) { TraceScreen* TraceScreen_new(Process* process) {
TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen)); TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen));
this->process = process; this->process = process;
this->display = Panel_new(0, 1, COLS, LINES-2, false, Class(ListItem)); this->display = Panel_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true, ListItem_compare);
this->bar = FunctionBar_new(3, tbFunctions, tbKeys, tbEvents);
this->tracing = true; this->tracing = true;
return this; return this;
} }
void TraceScreen_delete(TraceScreen* this) { void TraceScreen_delete(TraceScreen* this) {
Panel_delete((Object*)this->display); Panel_delete((Object*)this->display);
FunctionBar_delete((Object*)this->bar);
free(this); free(this);
} }
static void TraceScreen_draw(TraceScreen* this, IncSet* inc) { static void TraceScreen_draw(TraceScreen* this) {
attrset(CRT_colors[PANEL_HEADER_FOCUS]); attrset(CRT_colors[PANEL_HEADER_FOCUS]);
mvhline(0, 0, ' ', COLS); mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm); mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
attrset(CRT_colors[DEFAULT_COLOR]); attrset(CRT_colors[DEFAULT_COLOR]);
IncSet_drawBar(inc); FunctionBar_draw(this->bar, NULL);
}
static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) {
Vector_add(lines, (Object*) ListItem_new(line, 0));
if (!incFilter || String_contains_i(line, incFilter))
Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1));
}
static inline void appendLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) {
ListItem* last = (ListItem*)Vector_get(lines, Vector_size(lines)-1);
ListItem_append(last, line);
if (incFilter && Panel_get(panel, Panel_size(panel)-1) != (Object*)last && String_contains_i(line, incFilter))
Panel_add(panel, (Object*)last);
} }
void TraceScreen_run(TraceScreen* this) { void TraceScreen_run(TraceScreen* this) {
@ -87,11 +71,9 @@ void TraceScreen_run(TraceScreen* this) {
if (child == -1) return; if (child == -1) return;
if (child == 0) { if (child == 0) {
dup2(fdpair[1], STDERR_FILENO); dup2(fdpair[1], STDERR_FILENO);
int ok = fcntl(fdpair[1], F_SETFL, O_NONBLOCK); fcntl(fdpair[1], F_SETFL, O_NONBLOCK);
if (ok != -1) {
sprintf(buffer, "%d", this->process->pid); sprintf(buffer, "%d", this->process->pid);
execlp("strace", "strace", "-p", buffer, NULL); execlp("strace", "strace", "-p", buffer, NULL);
}
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
write(fdpair[1], message, strlen(message)); write(fdpair[1], message, strlen(message));
exit(1); exit(1);
@ -100,37 +82,20 @@ void TraceScreen_run(TraceScreen* this) {
FILE* strace = fdopen(fdpair[0], "r"); FILE* strace = fdopen(fdpair[0], "r");
Panel* panel = this->display; Panel* panel = this->display;
int fd_strace = fileno(strace); int fd_strace = fileno(strace);
TraceScreen_draw(this);
CRT_disableDelay(); CRT_disableDelay();
bool contLine = false; bool contLine = false;
bool follow = false; bool follow = false;
bool looping = true; bool looping = true;
FunctionBar* bar = FunctionBar_new(tsFunctions, tsKeys, tsEvents);
IncSet* inc = IncSet_new(bar);
Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE);
TraceScreen_draw(this, inc);
while (looping) { while (looping) {
Panel_draw(panel, true);
const char* incFilter = IncSet_filter(inc);
if (inc->active)
move(LINES-1, CRT_cursorX);
int ch = getch();
if (ch == ERR) {
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
// FD_SET(STDIN_FILENO, &fds);
FD_SET(fd_strace, &fds); FD_SET(fd_strace, &fds);
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_usec = 500; tv.tv_sec = 0; tv.tv_usec = 500;
int ready = select(fd_strace+1, &fds, NULL, NULL, &tv); int ready = select(fd_strace+1, &fds, NULL, NULL, &tv);
int nread = 0; int nread = 0;
if (ready > 0 && FD_ISSET(fd_strace, &fds)) if (ready > 0)
nread = fread(buffer, 1, 1000, strace); nread = fread(buffer, 1, 1000, strace);
if (nread && this->tracing) { if (nread && this->tracing) {
char* line = buffer; char* line = buffer;
@ -139,24 +104,25 @@ void TraceScreen_run(TraceScreen* this) {
if (buffer[i] == '\n') { if (buffer[i] == '\n') {
buffer[i] = '\0'; buffer[i] = '\0';
if (contLine) { if (contLine) {
appendLine(line, lines, panel, incFilter); ListItem_append((ListItem*)Panel_get(panel,
Panel_getSize(panel)-1), line);
contLine = false; contLine = false;
} else { } else {
addLine(line, lines, panel, incFilter); Panel_add(panel, (Object*) ListItem_new(line, 0));
} }
line = buffer+i+1; line = buffer+i+1;
} }
} }
if (line < buffer+nread) { if (line < buffer+nread) {
addLine(line, lines, panel, incFilter); Panel_add(panel, (Object*) ListItem_new(line, 0));
buffer[nread] = '\0'; buffer[nread] = '\0';
contLine = true; contLine = true;
} }
if (follow) if (follow)
Panel_setSelected(panel, Panel_size(panel)-1); Panel_setSelected(panel, Panel_getSize(panel)-1);
Panel_draw(panel, true);
} }
} int ch = getch();
if (ch == KEY_MOUSE) { if (ch == KEY_MOUSE) {
MEVENT mevent; MEVENT mevent;
int ok = getmouse(&mevent); int ok = getmouse(&mevent);
@ -166,62 +132,36 @@ void TraceScreen_run(TraceScreen* this) {
follow = false; follow = false;
ch = 0; ch = 0;
} if (mevent.y == LINES - 1) } if (mevent.y == LINES - 1)
ch = FunctionBar_synthesizeEvent(inc->bar, mevent.x); ch = FunctionBar_synthesizeEvent(this->bar, mevent.x);
} }
if (inc->active) {
IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines);
continue;
}
switch(ch) { switch(ch) {
case ERR: case ERR:
continue; continue;
case KEY_HOME: case KEY_F(5):
Panel_setSelected(panel, 0); this->tracing = !this->tracing;
break; FunctionBar_setLabel(this->bar, KEY_F(5), this->tracing?"Stop Tracing ":"Resume Tracing ");
case KEY_END: TraceScreen_draw(this);
Panel_setSelected(panel, Panel_size(panel)-1);
break;
case KEY_F(3):
case '/':
IncSet_activate(inc, INC_SEARCH);
break;
case KEY_F(4):
case '\\':
IncSet_activate(inc, INC_FILTER);
break; break;
case 'f': case 'f':
case KEY_F(8): case KEY_F(4):
follow = !follow; follow = !follow;
if (follow) if (follow)
Panel_setSelected(panel, Panel_size(panel)-1); Panel_setSelected(panel, Panel_getSize(panel)-1);
break;
case 't':
case KEY_F(9):
this->tracing = !this->tracing;
FunctionBar_setLabel(bar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing ");
TraceScreen_draw(this, inc);
break; break;
case 'q': case 'q':
case 27: case 27:
case KEY_F(10):
looping = false; looping = false;
break; break;
case KEY_RESIZE: case KEY_RESIZE:
Panel_resize(panel, COLS, LINES-2); Panel_resize(panel, COLS, LINES-2);
TraceScreen_draw(this, inc); TraceScreen_draw(this);
break; break;
default: default:
follow = false; follow = false;
Panel_onKey(panel, ch); Panel_onKey(panel, ch);
} }
Panel_draw(panel, true);
} }
IncSet_delete(inc);
FunctionBar_delete((Object*)bar);
Vector_delete(lines);
kill(child, SIGTERM); kill(child, SIGTERM);
waitpid(child, NULL, 0); waitpid(child, NULL, 0);
fclose(strace); fclose(strace);

View File

@ -9,13 +9,26 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ProcessList.h"
#include "Process.h" #include "Process.h"
#include "ListItem.h"
#include "Panel.h" #include "Panel.h"
#include "FunctionBar.h" #include "FunctionBar.h"
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; Process* process;
Panel* display; Panel* display;
FunctionBar* bar;
bool tracing; bool tracing;
} TraceScreen; } TraceScreen;

View File

@ -1,37 +1,33 @@
/* /*
htop - UptimeMeter.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "UptimeMeter.h" #include "UptimeMeter.h"
#include "Meter.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "CRT.h" #include "CRT.h"
#include <math.h> #include "debug.h"
/*{
#include "Meter.h"
}*/
int UptimeMeter_attributes[] = { int UptimeMeter_attributes[] = {
UPTIME UPTIME
}; };
static void UptimeMeter_setValues(Meter* this, char* buffer, int len) { static void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
double uptime = 0; double uptime;
FILE* fd = fopen(PROCDIR "/uptime", "r"); FILE* fd = fopen(PROCDIR "/uptime", "r");
if (fd) { fscanf(fd, "%lf", &uptime);
fscanf(fd, "%64lf", &uptime);
fclose(fd); fclose(fd);
}
int totalseconds = (int) ceil(uptime); int totalseconds = (int) ceil(uptime);
int seconds = totalseconds % 60; int seconds = totalseconds % 60;
int minutes = (totalseconds/60) % 60; int minutes = (totalseconds-seconds) % 3600 / 60;
int hours = (totalseconds/3600) % 24; int hours = (totalseconds-seconds-(minutes*60)) % 86400 / 3600;
int days = (totalseconds/86400); int days = (totalseconds-seconds-(minutes*60)-(hours*3600)) / 86400;
this->values[0] = days; this->values[0] = days;
if (days > this->total) { if (days > this->total) {
this->total = days; this->total = days;
@ -49,13 +45,11 @@ static void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
snprintf(buffer, len, "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds); snprintf(buffer, len, "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds);
} }
MeterClass UptimeMeter_class = { MeterType UptimeMeter = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.setValues = UptimeMeter_setValues, .setValues = UptimeMeter_setValues,
.defaultMode = TEXT_METERMODE, .display = NULL,
.mode = TEXT_METERMODE,
.items = 1,
.total = 100.0, .total = 100.0,
.attributes = UptimeMeter_attributes, .attributes = UptimeMeter_attributes,
.name = "Uptime", .name = "Uptime",

View File

@ -3,16 +3,22 @@
#ifndef HEADER_UptimeMeter #ifndef HEADER_UptimeMeter
#define HEADER_UptimeMeter #define HEADER_UptimeMeter
/* /*
htop - UptimeMeter.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Meter.h" #include "Meter.h"
#include "ProcessList.h"
#include "CRT.h"
#include "debug.h"
extern int UptimeMeter_attributes[]; extern int UptimeMeter_attributes[];
extern MeterClass UptimeMeter_class; extern MeterType UptimeMeter;
#endif #endif

View File

@ -1,25 +1,23 @@
/* /*
htop - UsersTable.c htop - UsersTable.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "UsersTable.h" #include "UsersTable.h"
#include "Hashtable.h"
#include "config.h" #include "String.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <strings.h> #include <strings.h>
#include <pwd.h> #include <pwd.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include "debug.h"
#include <assert.h> #include <assert.h>
/*{ /*{
#include "Hashtable.h"
typedef struct UsersTable_ { typedef struct UsersTable_ {
Hashtable* users; Hashtable* users;
} UsersTable; } UsersTable;
@ -42,7 +40,7 @@ char* UsersTable_getRef(UsersTable* this, unsigned int uid) {
if (name == NULL) { if (name == NULL) {
struct passwd* userData = getpwuid(uid); struct passwd* userData = getpwuid(uid);
if (userData != NULL) { if (userData != NULL) {
name = strdup(userData->pw_name); name = String_copy(userData->pw_name);
Hashtable_put(this->users, uid, name); Hashtable_put(this->users, uid, name);
} }
} }

View File

@ -4,12 +4,21 @@
#define HEADER_UsersTable #define HEADER_UsersTable
/* /*
htop - UsersTable.h htop - UsersTable.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Hashtable.h" #include "Hashtable.h"
#include "String.h"
#include <stdio.h>
#include <strings.h>
#include <pwd.h>
#include <sys/types.h>
#include "debug.h"
#include <assert.h>
typedef struct UsersTable_ { typedef struct UsersTable_ {
Hashtable* users; Hashtable* users;

238
Vector.c
View File

@ -1,38 +1,40 @@
/* /*
htop - Vector.c htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Vector.h" #include "Vector.h"
#include "Object.h"
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
/*{ #include "debug.h"
#include "Object.h" #include <assert.h>
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0) /*{
#ifndef DEFAULT_SIZE #ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1 #define DEFAULT_SIZE -1
#endif #endif
typedef void(*Vector_procedure)(void*);
typedef struct Vector_ { typedef struct Vector_ {
Object **array; Object **array;
ObjectClass* type; Object_Compare compare;
int arraySize; int arraySize;
int growthRate; int growthRate;
int items; int items;
char* vectorType;
bool owner; bool owner;
} Vector; } Vector;
}*/ }*/
Vector* Vector_new(ObjectClass* type, bool owner, int size) { Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare) {
Vector* this; Vector* this;
if (size == DEFAULT_SIZE) if (size == DEFAULT_SIZE)
@ -42,8 +44,9 @@ Vector* Vector_new(ObjectClass* type, bool owner, int size) {
this->array = (Object**) calloc(size, sizeof(Object*)); this->array = (Object**) calloc(size, sizeof(Object*));
this->arraySize = size; this->arraySize = size;
this->items = 0; this->items = 0;
this->type = type; this->vectorType = vectorType_;
this->owner = owner; this->owner = owner;
this->compare = compare;
return this; return this;
} }
@ -51,7 +54,7 @@ void Vector_delete(Vector* this) {
if (this->owner) { if (this->owner) {
for (int i = 0; i < this->items; i++) for (int i = 0; i < this->items; i++)
if (this->array[i]) if (this->array[i])
Object_delete(this->array[i]); (this->array[i])->delete(this->array[i]);
} }
free(this->array); free(this->array);
free(this); free(this);
@ -63,7 +66,7 @@ static inline bool Vector_isConsistent(Vector* this) {
assert(this->items <= this->arraySize); assert(this->items <= this->arraySize);
if (this->owner) { if (this->owner) {
for (int i = 0; i < this->items; i++) for (int i = 0; i < this->items; i++)
if (this->array[i] && !Object_isA(this->array[i], this->type)) if (this->array[i] && this->array[i]->class != this->vectorType)
return false; return false;
return true; return true;
} else { } else {
@ -85,202 +88,131 @@ int Vector_count(Vector* this) {
void Vector_prune(Vector* this) { void Vector_prune(Vector* this) {
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
if (this->owner) { int i;
for (int i = 0; i < this->items; i++)
for (i = 0; i < this->items; i++)
if (this->array[i]) { if (this->array[i]) {
Object_delete(this->array[i]); if (this->owner)
//this->array[i] = NULL; (this->array[i])->delete(this->array[i]);
} this->array[i] = NULL;
} }
this->items = 0; this->items = 0;
} }
static int comparisons = 0; void Vector_sort(Vector* this) {
assert(this->compare);
static int partition(Object** array, int left, int right, int pivotIndex, Object_Compare compare) {
void* pivotValue = array[pivotIndex];
swap(array, pivotIndex, right);
int storeIndex = left;
for (int i = left; i < right; i++) {
comparisons++;
if (compare(array[i], pivotValue) <= 0) {
swap(array, i, storeIndex);
storeIndex++;
}
}
swap(array, storeIndex, right);
return storeIndex;
}
static void quickSort(Object** array, int left, int right, Object_Compare compare) {
if (left >= right)
return;
int pivotIndex = (left+right) / 2;
int pivotNewIndex = partition(array, left, right, pivotIndex, compare);
quickSort(array, left, pivotNewIndex - 1, compare);
quickSort(array, pivotNewIndex + 1, right, compare);
}
// If I were to use only one sorting algorithm for both cases, it would probably be this one:
/*
static void combSort(Object** array, int left, int right, Object_Compare compare) {
int gap = right - left;
bool swapped = true;
while ((gap > 1) || swapped) {
if (gap > 1) {
gap = (int)((double)gap / 1.247330950103979);
}
swapped = false;
for (int i = left; gap + i <= right; i++) {
comparisons++;
if (compare(array[i], array[i+gap]) > 0) {
swap(array, i, i+gap);
swapped = true;
}
}
}
}
*/
static void insertionSort(Object** array, int left, int right, Object_Compare compare) {
for (int i = left+1; i <= right; i++) {
void* t = array[i];
int j = i - 1;
while (j >= left) {
comparisons++;
if (compare(array[j], t) <= 0)
break;
array[j+1] = array[j];
j--;
}
array[j+1] = t;
}
}
void Vector_quickSort(Vector* this) {
assert(this->type->compare);
assert(Vector_isConsistent(this));
quickSort(this->array, 0, this->items - 1, this->type->compare);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
Object_Compare compare = this->compare;
/* Insertion sort works best on mostly-sorted arrays. */
for (int i = 1; i < this->items; i++) {
int j;
void* t = this->array[i];
for (j = i-1; j >= 0 && compare(this->array[j], t) > 0; j--)
this->array[j+1] = this->array[j];
this->array[j+1] = t;
} }
void Vector_insertionSort(Vector* this) {
assert(this->type->compare);
assert(Vector_isConsistent(this));
insertionSort(this->array, 0, this->items - 1, this->type->compare);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
} }
static void Vector_checkArraySize(Vector* this) { static void Vector_checkArraySize(Vector* this) {
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
if (this->items >= this->arraySize) { if (this->items >= this->arraySize) {
//int i; int i;
//i = this->arraySize; i = this->arraySize;
this->arraySize = this->items + this->growthRate; this->arraySize = this->items + this->growthRate;
this->array = (Object**) realloc(this->array, sizeof(Object*) * this->arraySize); this->array = (Object**) realloc(this->array, sizeof(Object*) * this->arraySize);
//for (; i < this->arraySize; i++) for (; i < this->arraySize; i++)
// this->array[i] = NULL; this->array[i] = NULL;
} }
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
} }
void Vector_insert(Vector* this, int idx, void* data_) { void Vector_insert(Vector* this, int index, void* data_) {
assert(index >= 0);
assert(((Object*)data_)->class == this->vectorType);
Object* data = data_; Object* data = data_;
assert(idx >= 0);
assert(idx <= this->items);
assert(Object_isA(data, this->type));
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
Vector_checkArraySize(this); Vector_checkArraySize(this);
//assert(this->array[this->items] == NULL); assert(this->array[this->items] == NULL);
for (int i = this->items; i > idx; i--) { for (int i = this->items; i >= index; i--) {
this->array[i] = this->array[i-1]; this->array[i+1] = this->array[i];
} }
this->array[idx] = data; this->array[index] = data;
this->items++; this->items++;
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
} }
Object* Vector_take(Vector* this, int idx) { Object* Vector_take(Vector* this, int index) {
assert(idx >= 0 && idx < this->items); assert(index >= 0 && index < this->items);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
Object* removed = this->array[idx]; Object* removed = this->array[index];
//assert (removed != NULL); assert (removed != NULL);
this->items--; this->items--;
for (int i = idx; i < this->items; i++) for (int i = index; i < this->items; i++)
this->array[i] = this->array[i+1]; this->array[i] = this->array[i+1];
//this->array[this->items] = NULL; this->array[this->items] = NULL;
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
return removed; return removed;
} }
Object* Vector_remove(Vector* this, int idx) { Object* Vector_remove(Vector* this, int index) {
Object* removed = Vector_take(this, idx); Object* removed = Vector_take(this, index);
if (this->owner) { if (this->owner) {
Object_delete(removed); removed->delete(removed);
return NULL; return NULL;
} else } else
return removed; return removed;
} }
void Vector_moveUp(Vector* this, int idx) { void Vector_moveUp(Vector* this, int index) {
assert(idx >= 0 && idx < this->items); assert(index >= 0 && index < this->items);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
if (idx == 0) if (index == 0)
return; return;
Object* temp = this->array[idx]; Object* temp = this->array[index];
this->array[idx] = this->array[idx - 1]; this->array[index] = this->array[index - 1];
this->array[idx - 1] = temp; this->array[index - 1] = temp;
} }
void Vector_moveDown(Vector* this, int idx) { void Vector_moveDown(Vector* this, int index) {
assert(idx >= 0 && idx < this->items); assert(index >= 0 && index < this->items);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
if (idx == this->items - 1) if (index == this->items - 1)
return; return;
Object* temp = this->array[idx]; Object* temp = this->array[index];
this->array[idx] = this->array[idx + 1]; this->array[index] = this->array[index + 1];
this->array[idx + 1] = temp; this->array[index + 1] = temp;
} }
void Vector_set(Vector* this, int idx, void* data_) { void Vector_set(Vector* this, int index, void* data_) {
assert(index >= 0);
assert(((Object*)data_)->class == this->vectorType);
Object* data = data_; Object* data = data_;
assert(idx >= 0);
assert(Object_isA((Object*)data, this->type));
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
Vector_checkArraySize(this); Vector_checkArraySize(this);
if (idx >= this->items) { if (index >= this->items) {
this->items = idx+1; this->items = index+1;
} else { } else {
if (this->owner) { if (this->owner) {
Object* removed = this->array[idx]; Object* removed = this->array[index];
assert (removed != NULL); assert (removed != NULL);
if (this->owner) { if (this->owner) {
Object_delete(removed); removed->delete(removed);
} }
} }
} }
this->array[idx] = data; this->array[index] = data;
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
} }
#ifdef DEBUG inline Object* Vector_get(Vector* this, int index) {
assert(index < this->items);
inline Object* Vector_get(Vector* this, int idx) {
assert(idx < this->items);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
return this->array[idx]; return this->array[index];
} }
#else
#define Vector_get(v_, idx_) ((v_)->array[idx_])
#endif
inline int Vector_size(Vector* this) { inline int Vector_size(Vector* this) {
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
return this->items; return this->items;
@ -302,8 +234,8 @@ static void Vector_merge(Vector* this, Vector* v2) {
*/ */
void Vector_add(Vector* this, void* data_) { void Vector_add(Vector* this, void* data_) {
assert(data_ && ((Object*)data_)->class == this->vectorType);
Object* data = data_; Object* data = data_;
assert(Object_isA((Object*)data, this->type));
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
int i = this->items; int i = this->items;
Vector_set(this, this->items, data); Vector_set(this, this->items, data);
@ -312,15 +244,27 @@ void Vector_add(Vector* this, void* data_) {
} }
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) { inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
assert(((Object*)search_)->class == this->vectorType);
assert(this->compare);
Object* search = search_; Object* search = search_;
assert(Object_isA((Object*)search, this->type));
assert(compare);
assert(Vector_isConsistent(this)); assert(Vector_isConsistent(this));
for (int i = 0; i < this->items; i++) { for (int i = 0; i < this->items; i++) {
Object* o = (Object*)this->array[i]; Object* o = (Object*)this->array[i];
assert(o); if (o && compare(search, o) == 0)
if (compare(search, o) == 0)
return i; return i;
} }
return -1; return -1;
} }
/*
static void Vector_foreach(Vector* this, Vector_procedure f) {
int i;
assert(Vector_isConsistent(this));
for (i = 0; i < this->items; i++)
f(this->array[i]);
assert(Vector_isConsistent(this));
}
*/

View File

@ -3,31 +3,39 @@
#ifndef HEADER_Vector #ifndef HEADER_Vector
#define HEADER_Vector #define HEADER_Vector
/* /*
htop - Vector.h htop
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h" #include "Object.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)
#ifndef DEFAULT_SIZE #ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1 #define DEFAULT_SIZE -1
#endif #endif
typedef void(*Vector_procedure)(void*);
typedef struct Vector_ { typedef struct Vector_ {
Object **array; Object **array;
ObjectClass* type; Object_Compare compare;
int arraySize; int arraySize;
int growthRate; int growthRate;
int items; int items;
char* vectorType;
bool owner; bool owner;
} Vector; } Vector;
Vector* Vector_new(ObjectClass* type, bool owner, int size); Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare);
void Vector_delete(Vector* this); void Vector_delete(Vector* this);
@ -39,36 +47,21 @@ int Vector_count(Vector* this);
void Vector_prune(Vector* this); void Vector_prune(Vector* this);
// If I were to use only one sorting algorithm for both cases, it would probably be this one: void Vector_sort(Vector* this);
/*
*/ void Vector_insert(Vector* this, int index, void* data_);
void Vector_quickSort(Vector* this); Object* Vector_take(Vector* this, int index);
void Vector_insertionSort(Vector* this); Object* Vector_remove(Vector* this, int index);
void Vector_insert(Vector* this, int idx, void* data_); void Vector_moveUp(Vector* this, int index);
Object* Vector_take(Vector* this, int idx); void Vector_moveDown(Vector* this, int index);
Object* Vector_remove(Vector* this, int idx); void Vector_set(Vector* this, int index, void* data_);
void Vector_moveUp(Vector* this, int idx); extern Object* Vector_get(Vector* this, int index);
void Vector_moveDown(Vector* this, int idx);
void Vector_set(Vector* this, int idx, void* data_);
#ifdef DEBUG
extern Object* Vector_get(Vector* this, int idx);
#else
#define Vector_get(v_, idx_) ((v_)->array[idx_])
#endif
extern int Vector_size(Vector* this); extern int Vector_size(Vector* this);
@ -80,4 +73,8 @@ void Vector_add(Vector* this, void* data_);
extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare); extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
/*
*/
#endif #endif

1
acinclude.m4 Normal file
View File

@ -0,0 +1 @@
m4_include(plpa-1.1/plpa.m4)

View File

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/sh
aclocal -I m4 aclocal
autoconf autoconf
autoheader autoheader
libtoolize --copy --force libtoolize --copy
automake --add-missing --copy automake --add-missing --copy

View File

@ -1,36 +1,37 @@
# -*- Autoconf -*- # -*- Autoconf -*-
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ(2.65) AC_PREREQ(2.57)
AC_INIT([htop],[1.0.3],[hisham@gobolinux.org]) AC_INIT([htop],[0.8],[loderunner@users.sourceforge.net])
AM_INIT_AUTOMAKE
# The following two lines are required by hwloc scripts
AC_USE_SYSTEM_EXTENSIONS
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([1.11])
AC_CONFIG_SRCDIR([htop.c]) AC_CONFIG_SRCDIR([htop.c])
AC_CONFIG_HEADER([config.h]) AC_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_DISABLE_SHARED AM_DISABLE_SHARED
AC_ENABLE_STATIC AM_ENABLE_STATIC
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
# Checks for libraries. # Checks for libraries.
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
AC_MSG_ERROR([missing libraries: $missing_libraries])
fi
# Checks for header files. # Checks for header files.
AC_HEADER_DIRENT AC_HEADER_DIRENT
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h string.h strings.h sys/param.h sys/time.h unistd.h],[:],[ AC_CHECK_HEADERS([stdlib.h string.h strings.h sys/param.h sys/time.h unistd.h curses.h],[:],[
missing_headers="$missing_headers $ac_header" missing_headers="$missing_headers $ac_header"
]) ])
AC_CHECK_HEADERS([execinfo.h],[:],[:])
if test ! -z "$missing_headers"; then
AC_MSG_ERROR([missing headers: $missing_headers])
fi
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL AC_HEADER_STDBOOL
@ -40,6 +41,8 @@ AC_TYPE_UID_T
# Checks for library functions. # Checks for library functions.
AC_FUNC_CLOSEDIR_VOID AC_FUNC_CLOSEDIR_VOID
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_TYPE_SIGNAL AC_TYPE_SIGNAL
AC_FUNC_STAT AC_FUNC_STAT
AC_CHECK_FUNCS([memmove strncasecmp strstr strdup]) AC_CHECK_FUNCS([memmove strncasecmp strstr strdup])
@ -66,89 +69,26 @@ 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 fi
AC_ARG_ENABLE(cgroup, [AC_HELP_STRING([--enable-cgroup], [enable cgroups support])], ,enable_cgroup="no")
if test "x$enable_cgroup" = xyes; then
AC_DEFINE(HAVE_CGROUP, 1, [Define if cgroup support enabled.])
fi
AC_ARG_ENABLE(vserver, [AC_HELP_STRING([--enable-vserver], [enable VServer support])], ,enable_vserver="no")
if test "x$enable_vserver" = xyes; then
AC_DEFINE(HAVE_VSERVER, 1, [Define if vserver support enabled.])
fi
AC_ARG_ENABLE(ancient_vserver, [AC_HELP_STRING([--enable-ancient-vserver], [enable ancient VServer support (implies --enable-vserver)])], ,enable_ancient_vserver="no")
if test "x$enable_ancient_vserver" = xyes; then
AC_DEFINE(HAVE_VSERVER, 1, [Define if vserver support enabled.])
AC_DEFINE(HAVE_ANCIENT_VSERVER, 1, [Define if ancient vserver support enabled.])
fi
AC_ARG_ENABLE(taskstats, [AC_HELP_STRING([--enable-taskstats], [enable per-task IO Stats (taskstats kernel sup required)])], ,enable_taskstats="yes") AC_ARG_ENABLE(taskstats, [AC_HELP_STRING([--enable-taskstats], [enable per-task IO Stats (taskstats kernel sup required)])], ,enable_taskstats="yes")
if test "x$enable_taskstats" = xyes; then if test "x$enable_taskstats" = xyes; then
AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.]) AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.])
fi fi
AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes") AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="no")
if test "x$enable_unicode" = xyes; then if test "x$enable_unicode" = xyes; then
AC_CHECK_LIB([ncursesw], [refresh], [], [ AC_CHECK_LIB([ncursesw], [refresh], [], [missing_libraries="$missing_libraries libncursesw"])
missing_libraries="$missing_libraries libncursesw"
AC_MSG_ERROR([You may want to use --disable-unicode or install libncursesw.])
])
AC_CHECK_HEADERS([ncursesw/curses.h],[:],
[AC_CHECK_HEADERS([ncurses/ncurses.h],[:],
[AC_CHECK_HEADERS([ncurses/curses.h],[:],
[AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])])])
else else
AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"]) AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"])
AC_CHECK_HEADERS([curses.h],[:],
[AC_CHECK_HEADERS([ncurses/curses.h],[:],
[AC_CHECK_HEADERS([ncurses/ncurses.h],[:],
[AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])])])
fi fi
if test ! -z "$missing_libraries"; then
AC_MSG_ERROR([missing libraries: $missing_libraries])
fi
if test ! -z "$missing_headers"; then
AC_MSG_ERROR([missing headers: $missing_headers])
fi
if test "x$cross_compiling" = xno; then
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.))
AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.))
PLPA_INCLUDED(plpa-1.1)
PLPA_INIT(plpa_happy=yes, plpa_happy=no)
if test "x$plpa_happy" = xno; then
AC_MSG_ERROR([Failed to initialize PLPA.])
fi fi
AC_ARG_ENABLE(native_affinity, [AC_HELP_STRING([--enable-native-affinity], [enable native sched_setaffinity and sched_getaffinity for affinity support, disables hwloc])], ,enable_native_affinity="yes") AC_CONFIG_FILES([Makefile])
if test "x$enable_native_affinity" = xyes -a "x$cross_compiling" = xno; then
AC_MSG_CHECKING([for usable sched_setaffinity])
AC_RUN_IFELSE([
AC_LANG_PROGRAM([[
#include <sched.h>
#include <errno.h>
static cpu_set_t cpuset;
]], [[
CPU_ZERO(&cpuset);
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
if (errno == ENOSYS) return 1;
]])],
[AC_MSG_RESULT([yes])],
[enable_native_affinity=no
AC_MSG_RESULT([no])])
fi
if test "x$enable_native_affinity" = xyes; then
AC_DEFINE(HAVE_NATIVE_AFFINITY, 1, [Define if native sched_setaffinity and sched_getaffinity are to be used.])
fi
AC_ARG_ENABLE(hwloc, [AC_HELP_STRING([--enable-hwloc], [enable hwloc support for CPU affinity])],, enable_hwloc="no")
if test "x$enable_hwloc" = xyes
then
AC_CHECK_LIB([hwloc], [hwloc_linux_get_tid_cpubind], [], [missing_libraries="$missing_libraries libhwloc"])
AC_CHECK_HEADERS([hwloc.h],[:], [missing_headers="$missing_headers $ac_header"])
fi
AC_ARG_ENABLE(oom, [AC_HELP_STRING([--enable-oom], [enable OOM score reporting])], ,enable_oom="no")
if test "x$enable_oom" = xyes; then
AC_DEFINE(HAVE_OOM, 1, [Define if OOM score support enabled.])
fi
AC_CONFIG_FILES([Makefile htop.1])
AC_OUTPUT AC_OUTPUT

28
debug.h Normal file
View File

@ -0,0 +1,28 @@
#if defined(DEBUG)
/* Full debug */
#include "DebugMemory.h"
#define calloc(a, b) DebugMemory_calloc(a, b, __FILE__, __LINE__)
#define malloc(x) DebugMemory_malloc(x, __FILE__, __LINE__, #x)
#define realloc(x,s) DebugMemory_realloc(x, s, __FILE__, __LINE__, #x)
#define strdup(x) DebugMemory_strdup(x, __FILE__, __LINE__)
#define free(x) DebugMemory_free(x, __FILE__, __LINE__)
#define debug_done() DebugMemory_report()
#elif defined(DEBUGLITE)
/* Assertions and core only */
#ifdef NDEBUG
#undef NDEBUG
#endif
#define debug_done() sleep(0)
#else
/* No debugging */
#define NDEBUG
#define debug_done() sleep(0)
#endif

123
htop.1 Normal file
View File

@ -0,0 +1,123 @@
.TH "htop" "1" "0.8" "Bartosz Fenski <fenio@o2.pl>" "Utils"
.SH "NAME"
htop \- interactive process viewer
.SH "SYNTAX"
.LP
.B htop
.SH "DESCRIPTION"
.LP
This program is a free (GPL) ncurses-based process viewer.
.LP
It is similar to top, but allows to scroll the list vertically and
horizontally to see all processes and their full command lines.
.LP
Tasks related to processes (killing, renicing) can be done without
entering their PIDs.
.br
.SH "INTERACTIVE COMMANDS"
.LP
The following commands are supported:
.LP
.TP 5
.B Arrows, PgUP, PgDn, Home, End
Scroll process list.
.TP
.B Space
"Tag": mark a process. Commands that can operate on multiple processes,
like "kill", will then apply over the list of tagged processes, instead
of the currently highlighted one.
.TP
.B U
"Untag" all processes (remove all tags added with the Space key).
.TP
.B s
Trace process system calls: if strace(1) is installed, pressing this key
will attach it to the currently selected process, presenting a live
update of system calls issued by the process.
.TP
.B F1, h
Help screen
.TP
.B F2, S
Setup screen. There you can configure meters displayed on the top side
of the screen, as well as set various display options, choose among
color schemes and select the layout of the displayed columns.
.TP
.B F3, /
Incremental process search: type in part of a process command line and
the selection highlight will be moved to it. While in search mode,
pressing this key will cycle through matching occurrences.
.TP
.B F4, I
Invert sort order: if sort order is increasing, switch to decreasing,
and vice-versa.
.TP
.B F5, t
Tree view: organize processes by parenthood, and layout the relations
between them as a tree. Toggling the key will switch between tree and
your previously selected sort view. Selecting a sort view will exit
tree view.
.TP
.B F6, >
Select field for sorting. The sort field is indicated by a
highlight in the header.
.TP
.B F7, ], -
Increase selected process priority (subtract from 'nice' value).
This can be done by the superuser only.
.TP
.B F8, [, +
Decrease selected process priority (add to 'nice' value)
.TP
.B F9, k
"Kill" process: sends a signal which is selected in a menu, to one or a group
of processes. If processes were tagged, sends the signal to all tagged processes.
If none is tagged, sends to the currently selected process.
.TP
.B F10, q
Quit
.TP
.B a (on multiprocessor machines)
Set CPU affinity: mark which CPUs a process is allowed to use.
.TP
.B u
Show only processes owned by a specified user.
.TP
.B M
Sort by memory usage (top compatibility key).
.TP
.B P
Sort by processor usage (top compatibility key).
.TP
.B T
Sort by time (top compatibility key).
.TP
.B F
"Follow" process: if the sort order causes the currently selected process
to move in the list, make the selection bar follow it. This is useful for
monitoring a process: this way, you can keep a process always visible on
screen. When a movement key is used, "follow" loses effect.
.TP
.B K
Hide kernel threads: prevent the threads belonging the kernel to be
displayed in the process list. (This is a toggle key.)
.TP
.B H
Hide user threads: on systems that represent them differently than ordinary
processes (such as recent NPTL-based systems), this can hide threads from
userspace processes in the process list. (This is a toggle key.)
.TP
.B Ctrl-L
Refresh: redraw screen and recalculate values.
.TP
.B Numbers
PID search: type in process ID and the selection highlight will be moved to it.
.PD
.SH "AUTHORS"
.LP
htop is developed by Hisham Muhammad <loderunner@users.sourceforge.net>.
.br
This man page was written by Bartosz Fenski <fenio@o2.pl> for the
Debian GNU/Linux distribution (but it may be used by others), and
updated by Hisham Muhammad.

333
htop.1.in
View File

@ -1,333 +0,0 @@
.TH "HTOP" "1" "2011" "@PACKAGE_STRING@" "Utils"
.SH "NAME"
htop \- interactive process viewer
.SH "SYNOPSIS"
.LP
.B htop [\fI\-dChusv\fR]
.SH "DESCRIPTION"
.LP
Htop is a free (GPL) ncurses-based process viewer for Linux.
.LP
It is similar to top, but allows you to scroll vertically and horizontally,
so you can see all the processes running on the system, along with their full
command lines.
.LP
Tasks related to processes (killing, renicing) can be done without
entering their PIDs.
.br
.SH "COMMAND-LINE OPTIONS"
.LP
Mandatory arguments to long options are mandatory for short options too.
.LP
.TP
\fB\-d \-\-delay=DELAY\fR
Delay between updates, in tenths of seconds
.TP
\fB\-C \-\-no-color \-\-no-colour\fR
Start htop in monochrome mode
.TP
\fB\-h \-\-help
Display a help message and exit
.TP
\fB\-p \-\-pid=PID,PID...\fR
Show only the given PIDs
.TP
\fB\-s \-\-sort\-key COLUMN\fR
Sort by this column (use \-\-sort\-key help for a column list)
.TP
\fB\-u \-\-user=USERNAME\fR
Show only the processes of a given user
.TP
\fB\-v \-\-version
Output version information and exit
.PP
.br
.SH "INTERACTIVE COMMANDS"
.LP
The following commands are supported while in htop:
.LP
.TP 5
.B Arrows, PgUP, PgDn, Home, End
Scroll the process list.
.TP
.B Space
Tag or untag a process. Commands that can operate on multiple processes,
like "kill", will then apply over the list of tagged processes, instead
of the currently highlighted one.
.TP
.B U
Untag all processes (remove all tags added with the Space key).
.TP
.B s
Trace process system calls: if strace(1) is installed, pressing this key
will attach it to the currently selected process, presenting a live
update of system calls issued by the process.
.TP
.B l
Display open files for a process: if lsof(1) is installed, pressing this key
will display the list of file descriptors opened by the process.
.TP
.B F1, h, ?
Go to the help screen
.TP
.B F2, S
Go to the setup screen, where you can configure the meters displayed at the top
of the screen, set various display options, choose among color schemes, and
select which columns are displayed, in which order.
.TP
.B F3, /
Incrementally search the command lines of all the displayed processes. The
currently selected (highlighted) command will update as you type. While in
search mode, pressing F3 will cycle through matching occurrences.
.TP
.B F4, \\\\
Incremental process filtering: type in part of a process command line and
only processes whose names match will be shown. To cancel filtering,
enter the Filter option again and press Esc.
.TP
.B F5, t
Tree view: organize processes by parenthood, and layout the relations
between them as a tree. Toggling the key will switch between tree and
your previously selected sort view. Selecting a sort view will exit
tree view.
.TP
.B F6
On sorted view, select a field for sorting, also accessible through < and >.
The current sort field is indicated by a highlight in the header.
On tree view, expand or collapse the current subtree. A "+" indicator in the
tree node indicates that it is collapsed.
.TP
.B F7, ]
Increase the selected process's priority (subtract from 'nice' value).
This can only be done by the superuser.
.TP
.B F8, [
Decrease the selected process's priority (add to 'nice' value)
.TP
.B F9, k
"Kill" process: sends a signal which is selected in a menu, to one or a group
of processes. If processes were tagged, sends the signal to all tagged processes.
If none is tagged, sends to the currently selected process.
.TP
.B F10, q
Quit
.TP
.B I
Invert the sort order: if sort order is increasing, switch to decreasing, and
vice-versa.
.TP
.B +, \-
When in tree view mode, expand or collapse subtree. When a subtree is collapsed
a "+" sign shows to the left of the process name.
.TP
.B a (on multiprocessor machines)
Set CPU affinity: mark which CPUs a process is allowed to use.
.TP
.B u
Show only processes owned by a specified user.
.TP
.B M
Sort by memory usage (top compatibility key).
.TP
.B P
Sort by processor usage (top compatibility key).
.TP
.B T
Sort by time (top compatibility key).
.TP
.B F
"Follow" process: if the sort order causes the currently selected process
to move in the list, make the selection bar follow it. This is useful for
monitoring a process: this way, you can keep a process always visible on
screen. When a movement key is used, "follow" loses effect.
.TP
.B K
Hide kernel threads: prevent the threads belonging the kernel to be
displayed in the process list. (This is a toggle key.)
.TP
.B H
Hide user threads: on systems that represent them differently than ordinary
processes (such as recent NPTL-based systems), this can hide threads from
userspace processes in the process list. (This is a toggle key.)
.TP
.B Ctrl-L
Refresh: redraw screen and recalculate values.
.TP
.B Numbers
PID search: type in process ID and the selection highlight will be moved to it.
.PD
.SH "COLUMNS"
.LP
The following columns can display data about each process. A value of '\-' in
all the rows indicates that a column is unsupported on your system, or
currently unimplemented in htop. The names below are the ones used in the
"Available Columns" section of the setup screen. If a different name is
shown in htop's main screen, it is shown below in parenthesis.
.LP
.TP 5
.B Command
The full command line of the process (i.e program name and arguments).
.TP
.B PID
The process ID.
.TP
.B PPID
The parent process ID.
.TP
.B PGRP
The process's group ID.
.TP
.B SESSION (SESN)
The process's session ID.
.TP
.B TTY_NR (TTY)
The controlling terminal of the process.
.TP
.B TPGID
The process ID of the foreground process group of the controlling terminal.
.TP
.B STATE (S)
The state of the process:
\fBS\fR for sleeping (idle)
\fBR\fR for running
\fBD\fR for disk sleep (uninterruptible)
\fBZ\fR for zombie (waiting for parent to read its exit status)
\fBT\fR for traced or suspended (e.g by SIGTSTP)
\fBW\fR for paging
.TP
.B PROCESSOR (CPU)
The ID of the CPU the process last executed on.
.TP
.B NLWP
The number of threads in the process.
.TP
.B NICE (NI)
The nice value of a process, from 19 (low priority) to -20 (high priority). A
high value means the process is being nice, letting others have a higher
relative priority. Only root can lower the value.
.TP
.B PERCENT_CPU (CPU%)
The percentage of the CPU time that the process is currently using.
.TP
.B UTIME (UTIME+)
The user CPU time, which is the amount of time the process has spent executing
on the CPU in user mode (i.e everything but system calls), measured in clock
ticks.
.TP
.B STIME (STIME+)
The system CPU time, which is the amount of time the kernel has spent
executing system calls on behalf of the process, measured in clock ticks.
.TP
.B TIME (TIME+)
The time, measured in clock ticks that the process has spent in user and system
time (see UTIME, STIME above).
.TP
.B CUTIME
The children's user CPU time, which is the amount of time the process's
waited-for children have spent executing in user mode (see UTIME above).
.TP
.B CSTIME
The children's system CPU time, which is the amount of time the kernel has spent
executing system calls on behalf of all the process's waited-for children (see
STIME above).
.TP
.B PRIORITY (PRI)
The kernel's internal priority for the process, usually just its nice value
plus twenty. Different for real-time processes.
.TP
.B PERCENT_MEM
The percentage of memory the process is currently using (based on the process's
resident memory size, see M_RESIDENT below).
.TP
.B M_SIZE (VIRT)
Size in memory of the total program size.
.TP
.B M_RESIDENT (RES)
The resident set size, i.e the size of the text and data sections, plus stack
usage.
.TP
.B M_SHARE (SHR)
The size of the process's shared pages
.TP
.B M_TRS (CODE)
The size of the text segment of the process (i.e the size of the processes
executable instructions).
.TP
.B M_LRS (LIB)
The library size of the process.
.TP
.B M_DRS (DATA)
The size of the data segment plus stack usage of the process.
.TP
.B M_DT (DIRTY)
The size of the dirty pages of the process.
.TP
.B ST_UID (UID)
The user ID of the process owner.
.TP
.B USER
The username of the process owner, or the user ID if the name can't be
determined.
.TP
.B STARTTIME
The time the process was started.
.TP
.B RCHAR (RD_CHAR)
The number of bytes the process has read.
.TP
.B WCHAR (WR_CHAR)
The number of bytes the process has written.
.TP
.B SYSCR (RD_SYSC)
The number of read(2) syscalls for the process.
.TP
.B SYSCW (WR_SYSC)
The number of write(2) syscalls for the process.
.TP
.B RBYTES (IO_RBYTES)
Bytes of read(2) I/O for the process.
.TP
.B WBYTES (IO_WBYTES)
Bytes of write(2) I/O for the process.
.TP
.B IO_READ_RATE (IORR)
The I/O rate of read(2) in bytes per second, for the process.
.TP
.B IO_WRITE_RATE (IOWR)
The I/O rate of write(2) in bytes per second, for the process.
.TP
.B IO_RATE (IO)
The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above).
.TP
.B CNCLWB (IO_CANCEL)
Bytes of cancelled write(2) I/O.
.TP
.B CGROUP
Which cgroup the process is in.
.TP
.B CTID
OpenVZ container ID, a.k.a virtual environment ID.
.TP
.B VPID
OpenVZ process ID.
.TP
.B VXID
VServer process ID.
.TP
.B OOM
OOM killer score.
.TP
.B All other flags
Currently unsupported (always displays '-').
.SH "SEE ALSO"
proc(5), top(1), free(1), ps(1), uptime(1)
.SH "AUTHORS"
.LP
htop is developed by Hisham Muhammad <hisham@gobolinux.org>.
.LP
This man page was written by Bartosz Fenski <fenio@o2.pl> for the Debian
GNU/Linux distribution (but it may be used by others). It was updated by Hisham
Muhammad, and later by Vincent Launchbury, who wrote the 'Columns' section.

830
htop.c

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More