mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 13:34:35 +03:00
Compare commits
278 Commits
Author | SHA1 | Date | |
---|---|---|---|
43c3e4d3d9 | |||
9eec37c432 | |||
27da00f339 | |||
d5b3b6d692 | |||
616ee966d7 | |||
50b701258d | |||
814ce89b45 | |||
659251c501 | |||
e0209da88f | |||
4e2c2d7927 | |||
eb1cd4aca6 | |||
ab118c2dbe | |||
2f30cd1070 | |||
a939cdf827 | |||
100bd10b1d | |||
f86851766b | |||
6795d8b692 | |||
6fbc5a31da | |||
446d86c7a2 | |||
2fdebf6a29 | |||
34b89a9747 | |||
823bdbae13 | |||
1afbc19087 | |||
28d4cad5fe | |||
2ee1c41274 | |||
1de8762e71 | |||
d28b281165 | |||
b1564c2be9 | |||
79e390120a | |||
f239b62b90 | |||
f677843288 | |||
3fbd1ef76d | |||
30bafafb24 | |||
57b393f783 | |||
5b30280810 | |||
0a4ddab2a4 | |||
2bf8754bc2 | |||
f5a469b5a8 | |||
4027e5ee44 | |||
2f0a4b3d3a | |||
99bc23771f | |||
af02749722 | |||
4716a9857b | |||
1ac517be52 | |||
96858744b5 | |||
5d6ad853fa | |||
127f847ca5 | |||
19b438de10 | |||
af4c412ebf | |||
cb297af848 | |||
f2e4556b5e | |||
1d9e1b0118 | |||
369bef279a | |||
c0fc5bf898 | |||
f2a190b0e9 | |||
61bd770689 | |||
6d90e58c01 | |||
88ca9dcfa0 | |||
953ec71235 | |||
817e292ac9 | |||
11b251a577 | |||
96b57ea812 | |||
da236ca318 | |||
558b001e2b | |||
6fcceeff04 | |||
7afda7f5a1 | |||
5aac1733a6 | |||
76a715ee8c | |||
c1e0f6e17c | |||
4256c23d84 | |||
1c0e93c1bd | |||
cd692f27f4 | |||
7fd5e80429 | |||
8ace29c267 | |||
af285d1d3b | |||
6cfa9e0bf2 | |||
5c2d84aba3 | |||
322ba274ea | |||
ee5dc46fee | |||
a0810561f3 | |||
43a7231615 | |||
8d5dd51cf2 | |||
00b324bfc1 | |||
2a73405cd0 | |||
259e1a2938 | |||
f44a8f2009 | |||
1b21827f1f | |||
47e881f460 | |||
e6c6d7fbf7 | |||
6c71b7ed2d | |||
078b831696 | |||
0d8f654343 | |||
fae598fce8 | |||
ac36e4acbf | |||
90d567531a | |||
05a78c8111 | |||
bca656c79e | |||
368cb1fe20 | |||
571ae33bb4 | |||
1a604a05a5 | |||
58676d7001 | |||
ff8d54c221 | |||
8b73d11ac6 | |||
5b3cc559b2 | |||
45f7a4fc8d | |||
84281bdc44 | |||
81e44312b4 | |||
93233a67ea | |||
5b0b2255ef | |||
59d5eecdfd | |||
9c44f589d2 | |||
0bb8dba937 | |||
bfd86a60cc | |||
dfad0afb36 | |||
ae7e68321b | |||
bc87a8ff8c | |||
7ca1081712 | |||
3885648881 | |||
88f6de2352 | |||
539b32dc31 | |||
9f29e92777 | |||
e204861de5 | |||
4c4cceee5d | |||
ca6b9238a3 | |||
b45b9e2b33 | |||
9b87e52d41 | |||
c18ccdb910 | |||
d1b1cbc757 | |||
75080ce79d | |||
d25a0bc213 | |||
d1eff65fa5 | |||
1afef1899d | |||
ec17b7029a | |||
d07b043ee0 | |||
bb3e773c49 | |||
b288eb88c0 | |||
3e265ce4ab | |||
f1f77653e0 | |||
5a8307a10b | |||
978019d34f | |||
f7fe4b4722 | |||
4e72e790e3 | |||
31c995e663 | |||
a7bcf1d2e4 | |||
25a2aada3c | |||
03322b62ec | |||
11092662ee | |||
3f3213b2e2 | |||
60e5106098 | |||
636bb94fe6 | |||
27b470e10d | |||
5dfb46e14f | |||
7eeb52dfbb | |||
717758409e | |||
aa167adb90 | |||
da604d355a | |||
0a81172f62 | |||
300caa076e | |||
7a9615960f | |||
9599e5650e | |||
9b3514062f | |||
6382e03b68 | |||
bd459776a4 | |||
b57b7e9a9e | |||
219bb9ccff | |||
391eab2866 | |||
7d7118b1f6 | |||
a9c0ea3753 | |||
b561956637 | |||
8bdec7155e | |||
36ef1a93be | |||
72dbb72b68 | |||
4367e64b1d | |||
3e7822d660 | |||
5effb12e46 | |||
941ad72f67 | |||
831538b0f9 | |||
d8e1480a27 | |||
25551d44c1 | |||
9604e02106 | |||
e0f364a6f8 | |||
2960a8162e | |||
10f007e07e | |||
0ff54ebac9 | |||
d82e31be24 | |||
f919ed7cdf | |||
4e29c8235d | |||
3fcbcbfda6 | |||
5fd1436a92 | |||
f110ecdabb | |||
45de5694ac | |||
84ed4c01f6 | |||
b2fee47a14 | |||
40eac57aef | |||
6486229308 | |||
c166e172a8 | |||
0b0bd25e42 | |||
655c29bce5 | |||
65bc58ed50 | |||
9eb912149e | |||
bc4f7147cc | |||
6501432ef6 | |||
8d0fff2f66 | |||
dc262f4df6 | |||
22b0d7df64 | |||
b4a63409f5 | |||
282f16c4b8 | |||
a600d5a6e9 | |||
62a31673cb | |||
02a30bfecd | |||
5cc8998688 | |||
8f230920cd | |||
aff118ab39 | |||
23fc40976e | |||
ef31893067 | |||
c9e59b4a33 | |||
7dcd2beb90 | |||
a20ba78b5e | |||
1e124da059 | |||
dd86b9b646 | |||
2b53419983 | |||
3e6be2d7f7 | |||
4206828d17 | |||
7ee2646808 | |||
4488caa70a | |||
9b8d11d9f1 | |||
6330ff3a0a | |||
1371ee28a7 | |||
b62f9cea6f | |||
20bb68824d | |||
510213591b | |||
843aded57c | |||
31b3a2d2db | |||
385a7dbe1e | |||
3b950e4189 | |||
b93e5c00b6 | |||
10213f3ea1 | |||
f2ef3b74a0 | |||
ac5cecb6fc | |||
c3d682b0f6 | |||
dc38fc2da3 | |||
0baba6d7b4 | |||
a2f6eea0c4 | |||
11931f1bc8 | |||
c3550e18e8 | |||
a5dfaa2393 | |||
6beb27d803 | |||
ce3114079c | |||
15ab0ad706 | |||
23615d63a8 | |||
b09339d643 | |||
2338ad5820 | |||
fa6f919059 | |||
da23c8c5a1 | |||
12f4f09e6e | |||
460608d6e2 | |||
8fa33dc336 | |||
fa87ff0251 | |||
93f091c47e | |||
52840406ac | |||
4df76d127b | |||
5ed2b85c84 | |||
062433fe04 | |||
657b0f5efc | |||
37bb2fc5c7 | |||
cf7fdcd1d6 | |||
a839c3f2ca | |||
807df03671 | |||
bd0f30dcd6 | |||
855d9eaf9a | |||
b70b35ea65 | |||
a7c2aedcec | |||
46631b59fb | |||
e3acb5e07a | |||
5a91824e46 | |||
f356997269 | |||
e685bdeea0 | |||
4c51ad0e35 |
42
Affinity.c
Normal file
42
Affinity.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
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++;
|
||||
}
|
||||
|
27
Affinity.h
Normal file
27
Affinity.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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
|
74
AffinityPanel.c
Normal file
74
AffinityPanel.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 "CheckItem.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) {
|
||||
CheckItem* selected = (CheckItem*) Panel_getSelected(this);
|
||||
switch(ch) {
|
||||
case KEY_MOUSE:
|
||||
case ' ':
|
||||
CheckItem_set(selected, ! (CheckItem_get(selected)) );
|
||||
return HANDLED;
|
||||
case 0x0a:
|
||||
case 0x0d:
|
||||
case KEY_ENTER:
|
||||
return BREAK_LOOP;
|
||||
}
|
||||
return IGNORED;
|
||||
}
|
||||
|
||||
PanelClass AffinityPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.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:");
|
||||
int curCpu = 0;
|
||||
for (int i = 0; i < pl->cpuCount; i++) {
|
||||
char number[10];
|
||||
snprintf(number, 9, "%d", ProcessList_cpuId(pl, i));
|
||||
bool mode;
|
||||
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;
|
||||
}
|
||||
|
||||
Affinity* AffinityPanel_getAffinity(Panel* this) {
|
||||
Affinity* affinity = Affinity_new();
|
||||
int size = Panel_size(this);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (CheckItem_get((CheckItem*)Panel_get(this, i)))
|
||||
Affinity_add(affinity, i);
|
||||
}
|
||||
return affinity;
|
||||
}
|
23
AffinityPanel.h
Normal file
23
AffinityPanel.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* Do not edit this file. It was automatically generated. */
|
||||
|
||||
#ifndef 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 "Affinity.h"
|
||||
#include "ProcessList.h"
|
||||
#include "ListItem.h"
|
||||
|
||||
extern PanelClass AffinityPanel_class;
|
||||
|
||||
Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity);
|
||||
|
||||
Affinity* AffinityPanel_getAffinity(Panel* this);
|
||||
|
||||
#endif
|
@ -1,16 +1,23 @@
|
||||
/*
|
||||
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 "Settings.h"
|
||||
|
||||
#include "Header.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "ColumnsPanel.h"
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct AvailableColumnsPanel_ {
|
||||
Panel super;
|
||||
@ -22,15 +29,55 @@ typedef struct AvailableColumnsPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
static void AvailableColumnsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
AvailableColumnsPanel* this = (AvailableColumnsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||
AvailableColumnsPanel* this = (AvailableColumnsPanel*) super;
|
||||
char* text = ((ListItem*) Panel_getSelected(super))->value;
|
||||
HandlerResult result = IGNORED;
|
||||
|
||||
switch(ch) {
|
||||
case 13:
|
||||
case KEY_ENTER:
|
||||
case KEY_F(5):
|
||||
{
|
||||
int at = Panel_getSelectedIndex(this->columns);
|
||||
Panel_insert(this->columns, at, (Object*) ListItem_new(text, 0));
|
||||
Panel_setSelected(this->columns, at+1);
|
||||
ColumnsPanel_update(this->columns);
|
||||
result = HANDLED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (isalpha(ch))
|
||||
result = Panel_selectByTyping(super, ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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* this = (AvailableColumnsPanel*) malloc(sizeof(AvailableColumnsPanel));
|
||||
AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
|
||||
((Object*)this)->delete = AvailableColumnsPanel_delete;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
super->eventHandler = AvailableColumnsPanel_eventHandler;
|
||||
|
||||
Panel_setHeader(super, "Available Columns");
|
||||
|
||||
@ -41,32 +88,3 @@ AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* colu
|
||||
this->columns = columns;
|
||||
return this;
|
||||
}
|
||||
|
||||
void AvailableColumnsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
AvailableColumnsPanel* this = (AvailableColumnsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||
AvailableColumnsPanel* this = (AvailableColumnsPanel*) super;
|
||||
char* text = ((ListItem*) Panel_getSelected(super))->value;
|
||||
HandlerResult result = IGNORED;
|
||||
|
||||
switch(ch) {
|
||||
case 13:
|
||||
case KEY_ENTER:
|
||||
case KEY_F(5):
|
||||
{
|
||||
int at = Panel_getSelectedIndex(this->columns) + 1;
|
||||
if (at == Panel_getSize(this->columns))
|
||||
at--;
|
||||
Panel_insert(this->columns, at, (Object*) ListItem_new(text, 0));
|
||||
ColumnsPanel_update(this->columns);
|
||||
result = HANDLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2,17 +2,16 @@
|
||||
|
||||
#ifndef HEADER_AvailableColumnsPanel
|
||||
#define HEADER_AvailableColumnsPanel
|
||||
|
||||
#include "Settings.h"
|
||||
#include "Header.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "ColumnsPanel.h"
|
||||
/*
|
||||
htop - AvailableColumnsPanel.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 "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct AvailableColumnsPanel_ {
|
||||
Panel super;
|
||||
@ -23,10 +22,8 @@ typedef struct AvailableColumnsPanel_ {
|
||||
} AvailableColumnsPanel;
|
||||
|
||||
|
||||
extern PanelClass AvailableColumnsPanel_class;
|
||||
|
||||
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr);
|
||||
|
||||
void AvailableColumnsPanel_delete(Object* object);
|
||||
|
||||
HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch);
|
||||
|
||||
#endif
|
||||
|
@ -1,16 +1,23 @@
|
||||
/*
|
||||
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 "Settings.h"
|
||||
#include "Header.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "CPUMeter.h"
|
||||
#include "Header.h"
|
||||
#include "ListItem.h"
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*{
|
||||
#include "Settings.h"
|
||||
#include "Panel.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct AvailableMetersPanel_ {
|
||||
Panel super;
|
||||
@ -23,53 +30,19 @@ typedef struct AvailableMetersPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr) {
|
||||
AvailableMetersPanel* this = (AvailableMetersPanel*) malloc(sizeof(AvailableMetersPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
|
||||
((Object*)this)->delete = AvailableMetersPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->leftPanel = leftMeters;
|
||||
this->rightPanel = rightMeters;
|
||||
this->scr = scr;
|
||||
super->eventHandler = AvailableMetersPanel_EventHandler;
|
||||
|
||||
Panel_setHeader(super, "Available meters");
|
||||
for (int i = 1; Meter_types[i]; i++) {
|
||||
MeterType* type = Meter_types[i];
|
||||
if (type != &CPUMeter) {
|
||||
Panel_add(super, (Object*) ListItem_new(type->uiName, i << 16));
|
||||
}
|
||||
}
|
||||
MeterType* type = &CPUMeter;
|
||||
int processors = settings->pl->processorCount;
|
||||
if (processors > 1) {
|
||||
Panel_add(super, (Object*) ListItem_new("CPU average", 0));
|
||||
for (int i = 1; i <= processors; i++) {
|
||||
char buffer[50];
|
||||
sprintf(buffer, "%s %d", type->uiName, i);
|
||||
Panel_add(super, (Object*) ListItem_new(buffer, i));
|
||||
}
|
||||
} else {
|
||||
Panel_add(super, (Object*) ListItem_new("CPU", 1));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void AvailableMetersPanel_delete(Object* object) {
|
||||
static void AvailableMetersPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
AvailableMetersPanel* this = (AvailableMetersPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static inline void AvailableMetersPanel_addHeader(Header* header, Panel* panel, MeterType* type, int param, HeaderSide side) {
|
||||
static inline void AvailableMetersPanel_addHeader(Header* header, Panel* panel, MeterClass* type, int param, HeaderSide side) {
|
||||
Meter* meter = (Meter*) Header_addMeter(header, type, param, side);
|
||||
Panel_add(panel, (Object*) Meter_toListItem(meter));
|
||||
}
|
||||
|
||||
HandlerResult AvailableMetersPanel_EventHandler(Panel* super, int ch) {
|
||||
static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
|
||||
AvailableMetersPanel* this = (AvailableMetersPanel*) super;
|
||||
Header* header = this->settings->header;
|
||||
|
||||
@ -104,3 +77,43 @@ HandlerResult AvailableMetersPanel_EventHandler(Panel* super, int ch) {
|
||||
}
|
||||
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* this = AllocThis(AvailableMetersPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->leftPanel = leftMeters;
|
||||
this->rightPanel = rightMeters;
|
||||
this->scr = scr;
|
||||
|
||||
Panel_setHeader(super, "Available meters");
|
||||
for (int i = 1; Meter_types[i]; i++) {
|
||||
MeterClass* type = Meter_types[i];
|
||||
if (type != &CPUMeter_class) {
|
||||
Panel_add(super, (Object*) ListItem_new(type->uiName, i << 16));
|
||||
}
|
||||
}
|
||||
MeterClass* type = &CPUMeter_class;
|
||||
int cpus = settings->pl->cpuCount;
|
||||
if (cpus > 1) {
|
||||
Panel_add(super, (Object*) ListItem_new("CPU average", 0));
|
||||
for (int i = 1; i <= cpus; i++) {
|
||||
char buffer[50];
|
||||
sprintf(buffer, "%s %d", type->uiName, i);
|
||||
Panel_add(super, (Object*) ListItem_new(buffer, i));
|
||||
}
|
||||
} else {
|
||||
Panel_add(super, (Object*) ListItem_new("CPU", 1));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -2,17 +2,16 @@
|
||||
|
||||
#ifndef 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 "Header.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "CPUMeter.h"
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct AvailableMetersPanel_ {
|
||||
Panel super;
|
||||
@ -24,10 +23,8 @@ typedef struct AvailableMetersPanel_ {
|
||||
} AvailableMetersPanel;
|
||||
|
||||
|
||||
extern PanelClass AvailableMetersPanel_class;
|
||||
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr);
|
||||
|
||||
void AvailableMetersPanel_delete(Object* object);
|
||||
|
||||
HandlerResult AvailableMetersPanel_EventHandler(Panel* super, int ch);
|
||||
|
||||
#endif
|
||||
|
336
BatteryMeter.c
Normal file
336
BatteryMeter.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
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: "
|
||||
};
|
27
BatteryMeter.h
Normal file
27
BatteryMeter.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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
17
COPYING
@ -337,3 +337,20 @@ proprietary programs. If your program is a subroutine library, you may
|
||||
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
|
||||
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.
|
||||
|
||||
|
357
CPUMeter.c
357
CPUMeter.c
@ -1,52 +1,26 @@
|
||||
/*
|
||||
htop - CPUMeter.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "CPUMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "CRT.h"
|
||||
#include "ProcessList.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
int CPUMeter_attributes[] = {
|
||||
CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IOWAIT, CPU_IRQ, CPU_SOFTIRQ
|
||||
};
|
||||
|
||||
MeterType CPUMeter = {
|
||||
.setValues = CPUMeter_setValues,
|
||||
.display = CPUMeter_display,
|
||||
.mode = BAR_METERMODE,
|
||||
.items = 6,
|
||||
.total = 100.0,
|
||||
.attributes = CPUMeter_attributes,
|
||||
.name = "CPU",
|
||||
.uiName = "CPU",
|
||||
.caption = "CPU",
|
||||
.init = CPUMeter_init
|
||||
};
|
||||
|
||||
MeterType AllCPUsMeter = {
|
||||
.mode = 0,
|
||||
.items = 1,
|
||||
.total = 100.0,
|
||||
.attributes = CPUMeter_attributes,
|
||||
.name = "AllCPUs",
|
||||
.uiName = "All CPUs",
|
||||
.caption = "CPU",
|
||||
.draw = AllCPUsMeter_draw,
|
||||
.init = AllCPUsMeter_init,
|
||||
.setMode = AllCPUsMeter_setMode,
|
||||
.done = AllCPUsMeter_done
|
||||
CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, CPU_IOWAIT
|
||||
};
|
||||
|
||||
#ifndef MIN
|
||||
@ -56,103 +30,318 @@ MeterType AllCPUsMeter = {
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
void CPUMeter_init(Meter* this) {
|
||||
int processor = this->param;
|
||||
if (this->pl->processorCount > 1) {
|
||||
static void CPUMeter_init(Meter* this) {
|
||||
int cpu = this->param;
|
||||
if (this->pl->cpuCount > 1) {
|
||||
char caption[10];
|
||||
sprintf(caption, "%-3d", processor);
|
||||
sprintf(caption, "%-3d", ProcessList_cpuId(this->pl, cpu - 1));
|
||||
Meter_setCaption(this, caption);
|
||||
}
|
||||
if (this->param == 0)
|
||||
Meter_setCaption(this, "Avg");
|
||||
}
|
||||
|
||||
void CPUMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
static void CPUMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
ProcessList* pl = this->pl;
|
||||
int processor = this->param;
|
||||
double total = (double) pl->totalPeriod[processor];
|
||||
double cpu;
|
||||
this->values[0] = pl->nicePeriod[processor] / total * 100.0;
|
||||
this->values[1] = pl->userPeriod[processor] / total * 100.0;
|
||||
if (pl->expandSystemTime) {
|
||||
this->values[2] = pl->systemPeriod[processor] / total * 100.0;
|
||||
this->values[3] = pl->ioWaitPeriod[processor] / total * 100.0;
|
||||
this->values[4] = pl->irqPeriod[processor] / total * 100.0;
|
||||
this->values[5] = pl->softIrqPeriod[processor] / total * 100.0;
|
||||
this->type->items = 6;
|
||||
cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2]+
|
||||
this->values[3]+this->values[4]+this->values[5])));
|
||||
} else {
|
||||
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])));
|
||||
int cpu = this->param;
|
||||
if (cpu > this->pl->cpuCount) {
|
||||
snprintf(buffer, size, "absent");
|
||||
return;
|
||||
}
|
||||
snprintf(buffer, size, "%5.1f%%", cpu );
|
||||
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) {
|
||||
v[2] = cpuData->systemPeriod / total * 100.0;
|
||||
v[3] = cpuData->irqPeriod / total * 100.0;
|
||||
v[4] = cpuData->softIrqPeriod / total * 100.0;
|
||||
v[5] = cpuData->stealPeriod / total * 100.0;
|
||||
v[6] = cpuData->guestPeriod / total * 100.0;
|
||||
v[7] = cpuData->ioWaitPeriod / total * 100.0;
|
||||
Meter_setItems(this, 8);
|
||||
if (pl->accountGuestInCPUMeter) {
|
||||
percent = v[0]+v[1]+v[2]+v[3]+v[4]+v[5]+v[6];
|
||||
} else {
|
||||
percent = v[0]+v[1]+v[2]+v[3]+v[4];
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
void CPUMeter_display(Object* cast, RichString* out) {
|
||||
static void CPUMeter_display(Object* cast, RichString* out) {
|
||||
char buffer[50];
|
||||
Meter* this = (Meter*)cast;
|
||||
RichString_init(out);
|
||||
RichString_prune(out);
|
||||
if (this->param > this->pl->cpuCount) {
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "absent");
|
||||
return;
|
||||
}
|
||||
sprintf(buffer, "%5.1f%% ", this->values[1]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], ":");
|
||||
RichString_append(out, CRT_colors[CPU_NORMAL], buffer);
|
||||
if (this->pl->expandSystemTime) {
|
||||
if (this->pl->detailedCPUTime) {
|
||||
sprintf(buffer, "%5.1f%% ", this->values[2]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "sy:");
|
||||
RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
|
||||
sprintf(buffer, "%5.1f%% ", this->values[0]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "ni:");
|
||||
RichString_append(out, CRT_colors[CPU_NICE], buffer);
|
||||
RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer);
|
||||
sprintf(buffer, "%5.1f%% ", this->values[3]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "wa:");
|
||||
RichString_append(out, CRT_colors[CPU_IOWAIT], buffer);
|
||||
sprintf(buffer, "%5.1f%% ", this->values[4]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "hi:");
|
||||
RichString_append(out, CRT_colors[CPU_IRQ], buffer);
|
||||
sprintf(buffer, "%5.1f%% ", this->values[4]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "si:");
|
||||
RichString_append(out, CRT_colors[CPU_SOFTIRQ], buffer);
|
||||
if (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[CPU_IOWAIT], buffer);
|
||||
} else {
|
||||
sprintf(buffer, "%5.1f%% ", this->values[2]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "sys:");
|
||||
RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
|
||||
sprintf(buffer, "%5.1f%% ", this->values[0]);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "low:");
|
||||
RichString_append(out, CRT_colors[CPU_NICE], buffer);
|
||||
RichString_append(out, CRT_colors[CPU_NICE_TEXT], 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AllCPUsMeter_init(Meter* this) {
|
||||
int processors = this->pl->processorCount;
|
||||
this->drawBuffer = malloc(sizeof(Meter*) * processors);
|
||||
Meter** meters = (Meter**) this->drawBuffer;
|
||||
for (int i = 0; i < processors; i++)
|
||||
meters[i] = Meter_new(this->pl, i+1, &CPUMeter);
|
||||
this->h = processors;
|
||||
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) {
|
||||
int cpus = this->pl->cpuCount;
|
||||
if (!this->drawData)
|
||||
this->drawData = calloc(cpus, sizeof(Meter*));
|
||||
Meter** meters = (Meter**) this->drawData;
|
||||
int start, count;
|
||||
AllCPUsMeter_getRange(this, &start, &count);
|
||||
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;
|
||||
int h = Meter_modes[this->mode]->h;
|
||||
if (strchr(Meter_name(this), '2'))
|
||||
this->h = h * ((count+1) / 2);
|
||||
else
|
||||
this->h = h * count;
|
||||
}
|
||||
|
||||
void AllCPUsMeter_done(Meter* this) {
|
||||
int processors = this->pl->processorCount;
|
||||
Meter** meters = (Meter**) this->drawBuffer;
|
||||
for (int i = 0; i < processors; i++)
|
||||
static void AllCPUsMeter_done(Meter* this) {
|
||||
Meter** meters = (Meter**) this->drawData;
|
||||
int start, count;
|
||||
AllCPUsMeter_getRange(this, &start, &count);
|
||||
for (int i = 0; i < count; i++)
|
||||
Meter_delete((Object*)meters[i]);
|
||||
}
|
||||
|
||||
void AllCPUsMeter_setMode(Meter* this, int mode) {
|
||||
static void AllCPUsMeter_updateMode(Meter* this, int mode) {
|
||||
Meter** meters = (Meter**) this->drawData;
|
||||
this->mode = mode;
|
||||
int processors = this->pl->processorCount;
|
||||
int h = Meter_modes[this->mode]->h;
|
||||
this->h = h * processors;
|
||||
int h = Meter_modes[mode]->h;
|
||||
int start, count;
|
||||
AllCPUsMeter_getRange(this, &start, &count);
|
||||
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;
|
||||
}
|
||||
|
||||
void AllCPUsMeter_draw(Meter* this, int x, int y, int w) {
|
||||
int processors = this->pl->processorCount;
|
||||
Meter** meters = (Meter**) this->drawBuffer;
|
||||
for (int i = 0; i < processors; i++) {
|
||||
Meter_setMode(meters[i], this->mode);
|
||||
static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) {
|
||||
Meter** meters = (Meter**) this->drawData;
|
||||
int start, count;
|
||||
AllCPUsMeter_getRange(this, &start, &count);
|
||||
int height = (count+1)/2;
|
||||
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);
|
||||
y += meters[i]->h;
|
||||
}
|
||||
}
|
||||
|
||||
MeterClass CPUMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = CPUMeter_display
|
||||
},
|
||||
.setValues = CPUMeter_setValues,
|
||||
.defaultMode = BAR_METERMODE,
|
||||
.maxItems = 8,
|
||||
.total = 100.0,
|
||||
.attributes = CPUMeter_attributes,
|
||||
.name = "CPU",
|
||||
.uiName = "CPU",
|
||||
.caption = "CPU",
|
||||
.init = CPUMeter_init
|
||||
};
|
||||
|
||||
MeterClass AllCPUsMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = CPUMeter_display
|
||||
},
|
||||
.defaultMode = CUSTOM_METERMODE,
|
||||
.total = 100.0,
|
||||
.attributes = CPUMeter_attributes,
|
||||
.name = "AllCPUs",
|
||||
.uiName = "CPUs (1/1)",
|
||||
.caption = "CPU",
|
||||
.draw = SingleColCPUsMeter_draw,
|
||||
.init = AllCPUsMeter_init,
|
||||
.updateMode = AllCPUsMeter_updateMode,
|
||||
.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
|
||||
};
|
||||
|
||||
|
31
CPUMeter.h
31
CPUMeter.h
@ -4,29 +4,15 @@
|
||||
#define HEADER_CPUMeter
|
||||
/*
|
||||
htop - CPUMeter.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(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"
|
||||
|
||||
#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 MeterType CPUMeter;
|
||||
|
||||
extern MeterType AllCPUsMeter;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
@ -34,18 +20,19 @@ extern MeterType AllCPUsMeter;
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
void CPUMeter_init(Meter* this);
|
||||
extern MeterClass CPUMeter_class;
|
||||
|
||||
void CPUMeter_setValues(Meter* this, char* buffer, int size);
|
||||
extern MeterClass AllCPUsMeter_class;
|
||||
|
||||
void CPUMeter_display(Object* cast, RichString* out);
|
||||
extern MeterClass AllCPUs2Meter_class;
|
||||
|
||||
void AllCPUsMeter_init(Meter* this);
|
||||
extern MeterClass LeftCPUsMeter_class;
|
||||
|
||||
void AllCPUsMeter_done(Meter* this);
|
||||
extern MeterClass RightCPUsMeter_class;
|
||||
|
||||
void AllCPUsMeter_setMode(Meter* this, int mode);
|
||||
extern MeterClass LeftCPUs2Meter_class;
|
||||
|
||||
extern MeterClass RightCPUs2Meter_class;
|
||||
|
||||
void AllCPUsMeter_draw(Meter* this, int x, int y, int w);
|
||||
|
||||
#endif
|
||||
|
209
CRT.c
209
CRT.c
@ -1,20 +1,24 @@
|
||||
/*
|
||||
htop - CRT.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include <curses.h>
|
||||
#include "config.h"
|
||||
#include "String.h"
|
||||
#include "RichString.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
|
||||
|
||||
@ -36,9 +40,8 @@ in the source distribution for its full text.
|
||||
|
||||
//#link curses
|
||||
|
||||
bool CRT_hasColors;
|
||||
|
||||
/*{
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum ColorElements_ {
|
||||
RESET_COLOR,
|
||||
@ -55,7 +58,7 @@ typedef enum ColorElements_ {
|
||||
METER_VALUE,
|
||||
LED_COLOR,
|
||||
UPTIME,
|
||||
TASKS_TOTAL,
|
||||
BATTERY,
|
||||
TASKS_RUNNING,
|
||||
SWAP,
|
||||
PROCESS,
|
||||
@ -67,6 +70,8 @@ typedef enum ColorElements_ {
|
||||
PROCESS_BASENAME,
|
||||
PROCESS_HIGH_PRIORITY,
|
||||
PROCESS_LOW_PRIORITY,
|
||||
PROCESS_THREAD,
|
||||
PROCESS_THREAD_BASENAME,
|
||||
BAR_BORDER,
|
||||
BAR_SHADOW,
|
||||
GRAPH_1,
|
||||
@ -80,6 +85,7 @@ typedef enum ColorElements_ {
|
||||
GRAPH_9,
|
||||
MEMORY_USED,
|
||||
MEMORY_BUFFERS,
|
||||
MEMORY_BUFFERS_TEXT,
|
||||
MEMORY_CACHE,
|
||||
LOAD,
|
||||
LOAD_AVERAGE_FIFTEEN,
|
||||
@ -89,28 +95,71 @@ typedef enum ColorElements_ {
|
||||
CHECK_MARK,
|
||||
CHECK_TEXT,
|
||||
CLOCK,
|
||||
HELP_BOLD,
|
||||
HOSTNAME,
|
||||
CPU_NICE,
|
||||
CPU_NICE_TEXT,
|
||||
CPU_NORMAL,
|
||||
CPU_KERNEL,
|
||||
HELP_BOLD,
|
||||
CPU_IOWAIT,
|
||||
CPU_IRQ,
|
||||
CPU_SOFTIRQ,
|
||||
CPU_STEAL,
|
||||
CPU_GUEST,
|
||||
LAST_COLORELEMENT
|
||||
} ColorElements;
|
||||
|
||||
void CRT_fatalError(const char* note) __attribute__ ((noreturn));
|
||||
|
||||
}*/
|
||||
|
||||
// TODO: centralize these in Settings.
|
||||
|
||||
int CRT_delay = 0;
|
||||
static bool CRT_hasColors;
|
||||
|
||||
static int CRT_delay = 0;
|
||||
|
||||
int CRT_colorScheme = 0;
|
||||
|
||||
bool CRT_utf8 = false;
|
||||
|
||||
int CRT_colors[LAST_COLORELEMENT] = { 0 };
|
||||
|
||||
int CRT_cursorX = 0;
|
||||
|
||||
int CRT_scrollHAmount = 5;
|
||||
|
||||
char* CRT_termType;
|
||||
|
||||
void *backtraceArray[128];
|
||||
|
||||
static void CRT_handleSIGSEGV(int sgn) {
|
||||
(void) sgn;
|
||||
CRT_done();
|
||||
#if __linux
|
||||
fprintf(stderr, "\n\nhtop " VERSION " aborting. Please report bug at http://hisham.hm/htop\n");
|
||||
#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) {
|
||||
(void) sgn;
|
||||
CRT_done();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// TODO: pass an instance of Settings instead.
|
||||
|
||||
void CRT_init(int delay, int colorScheme) {
|
||||
@ -118,7 +167,7 @@ void CRT_init(int delay, int colorScheme) {
|
||||
noecho();
|
||||
CRT_delay = delay;
|
||||
CRT_colorScheme = colorScheme;
|
||||
halfdelay(CRT_delay);
|
||||
halfdelay(CRT_delay/2);
|
||||
nonl();
|
||||
intrflush(stdscr, false);
|
||||
keypad(stdscr, true);
|
||||
@ -130,9 +179,15 @@ void CRT_init(int delay, int colorScheme) {
|
||||
CRT_hasColors = false;
|
||||
}
|
||||
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")) {
|
||||
define_key("\033[H", KEY_HOME);
|
||||
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("\033OQ", KEY_F(2));
|
||||
define_key("\033OR", KEY_F(3));
|
||||
@ -160,12 +215,19 @@ void CRT_done() {
|
||||
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() {
|
||||
nocbreak();
|
||||
cbreak();
|
||||
nodelay(stdscr, FALSE);
|
||||
int ret = getch();
|
||||
halfdelay(CRT_delay);
|
||||
halfdelay(CRT_delay/2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -176,18 +238,7 @@ void CRT_disableDelay() {
|
||||
}
|
||||
|
||||
void CRT_enableDelay() {
|
||||
halfdelay(CRT_delay);
|
||||
}
|
||||
|
||||
void CRT_handleSIGSEGV(int signal) {
|
||||
CRT_done();
|
||||
fprintf(stderr, "Aborted. Please report bug at http://htop.sf.net");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void CRT_handleSIGTERM(int signal) {
|
||||
CRT_done();
|
||||
exit(0);
|
||||
halfdelay(CRT_delay/2);
|
||||
}
|
||||
|
||||
void CRT_setColors(int colorScheme) {
|
||||
@ -209,10 +260,11 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[FUNCTION_KEY] = A_NORMAL;
|
||||
CRT_colors[PANEL_HEADER_FOCUS] = A_REVERSE;
|
||||
CRT_colors[PANEL_HEADER_UNFOCUS] = A_REVERSE;
|
||||
CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE | A_BOLD;
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_REVERSE;
|
||||
CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE;
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD;
|
||||
CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD;
|
||||
CRT_colors[UPTIME] = A_BOLD;
|
||||
CRT_colors[BATTERY] = A_BOLD;
|
||||
CRT_colors[LARGE_NUMBER] = A_BOLD;
|
||||
CRT_colors[METER_TEXT] = A_NORMAL;
|
||||
CRT_colors[METER_VALUE] = A_BOLD;
|
||||
@ -227,6 +279,8 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_R_STATE] = A_BOLD;
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = A_BOLD;
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = A_DIM;
|
||||
CRT_colors[PROCESS_THREAD] = A_BOLD;
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_REVERSE;
|
||||
CRT_colors[BAR_BORDER] = A_BOLD;
|
||||
CRT_colors[BAR_SHADOW] = A_DIM;
|
||||
CRT_colors[SWAP] = A_BOLD;
|
||||
@ -241,22 +295,27 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = A_DIM;
|
||||
CRT_colors[MEMORY_USED] = A_BOLD;
|
||||
CRT_colors[MEMORY_BUFFERS] = A_NORMAL;
|
||||
CRT_colors[MEMORY_BUFFERS_TEXT] = A_NORMAL;
|
||||
CRT_colors[MEMORY_CACHE] = A_NORMAL;
|
||||
CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM;
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL;
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD;
|
||||
CRT_colors[LOAD] = 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[CHECK_BOX] = A_BOLD;
|
||||
CRT_colors[CHECK_MARK] = A_NORMAL;
|
||||
CRT_colors[CHECK_TEXT] = A_NORMAL;
|
||||
CRT_colors[CPU_IOWAIT] = A_BOLD;
|
||||
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_IRQ] = 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) {
|
||||
CRT_colors[RESET_COLOR] = ColorPair(Black,White);
|
||||
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,White);
|
||||
@ -268,6 +327,7 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,White);
|
||||
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
|
||||
CRT_colors[UPTIME] = ColorPair(Yellow,White);
|
||||
CRT_colors[BATTERY] = ColorPair(Yellow,White);
|
||||
CRT_colors[LARGE_NUMBER] = ColorPair(Red,White);
|
||||
CRT_colors[METER_TEXT] = ColorPair(Blue,White);
|
||||
CRT_colors[METER_VALUE] = ColorPair(Black,White);
|
||||
@ -277,11 +337,13 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_SHADOW] = A_BOLD | ColorPair(Black,White);
|
||||
CRT_colors[PROCESS_TAG] = ColorPair(White,Blue);
|
||||
CRT_colors[PROCESS_MEGABYTES] = ColorPair(Blue,White);
|
||||
CRT_colors[PROCESS_BASENAME] = ColorPair(Green,White);
|
||||
CRT_colors[PROCESS_TREE] = ColorPair(Blue,White);
|
||||
CRT_colors[PROCESS_BASENAME] = ColorPair(Blue,White);
|
||||
CRT_colors[PROCESS_TREE] = ColorPair(Green,White);
|
||||
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,White);
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White);
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,White);
|
||||
CRT_colors[PROCESS_THREAD] = ColorPair(Blue,White);
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,White);
|
||||
CRT_colors[BAR_BORDER] = ColorPair(Blue,White);
|
||||
CRT_colors[BAR_SHADOW] = ColorPair(Black,White);
|
||||
CRT_colors[SWAP] = ColorPair(Red,White);
|
||||
@ -296,22 +358,27 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = ColorPair(Yellow,White);
|
||||
CRT_colors[MEMORY_USED] = ColorPair(Green,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[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White);
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White);
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,White);
|
||||
CRT_colors[LOAD] = ColorPair(Black,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(White,White);
|
||||
CRT_colors[CLOCK] = ColorPair(Black,White);
|
||||
CRT_colors[CHECK_BOX] = ColorPair(Blue,White);
|
||||
CRT_colors[CHECK_MARK] = ColorPair(Black,White);
|
||||
CRT_colors[CHECK_TEXT] = ColorPair(Black,White);
|
||||
CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,White);
|
||||
CRT_colors[HOSTNAME] = ColorPair(Black,White);
|
||||
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_SOFTIRQ] = ColorPair(Blue,White);
|
||||
CRT_colors[CPU_STEAL] = ColorPair(Cyan,White);
|
||||
CRT_colors[CPU_GUEST] = ColorPair(Cyan,White);
|
||||
} else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE2) {
|
||||
CRT_colors[RESET_COLOR] = ColorPair(Black,Black);
|
||||
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,Black);
|
||||
@ -323,6 +390,7 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,Black);
|
||||
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
|
||||
CRT_colors[UPTIME] = ColorPair(Yellow,Black);
|
||||
CRT_colors[BATTERY] = ColorPair(Yellow,Black);
|
||||
CRT_colors[LARGE_NUMBER] = ColorPair(Red,Black);
|
||||
CRT_colors[METER_TEXT] = ColorPair(Blue,Black);
|
||||
CRT_colors[METER_VALUE] = ColorPair(Black,Black);
|
||||
@ -337,6 +405,8 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
|
||||
CRT_colors[PROCESS_THREAD] = ColorPair(Blue,Black);
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black);
|
||||
CRT_colors[BAR_BORDER] = ColorPair(Blue,Black);
|
||||
CRT_colors[BAR_SHADOW] = ColorPair(Black,Black);
|
||||
CRT_colors[SWAP] = ColorPair(Red,Black);
|
||||
@ -351,22 +421,27 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = ColorPair(Yellow,Black);
|
||||
CRT_colors[MEMORY_USED] = ColorPair(Green,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[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black);
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black);
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = ColorPair(Black,Black);
|
||||
CRT_colors[LOAD] = ColorPair(White,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[CHECK_BOX] = ColorPair(Blue,Black);
|
||||
CRT_colors[CHECK_MARK] = ColorPair(Black,Black);
|
||||
CRT_colors[CHECK_TEXT] = ColorPair(Black,Black);
|
||||
CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,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_IRQ] = A_BOLD | 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) {
|
||||
CRT_colors[RESET_COLOR] = ColorPair(White,Blue);
|
||||
CRT_colors[DEFAULT_COLOR] = ColorPair(White,Blue);
|
||||
@ -378,6 +453,7 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD | ColorPair(Yellow,Blue);
|
||||
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
|
||||
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[METER_TEXT] = ColorPair(Cyan,Blue);
|
||||
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Blue);
|
||||
@ -392,6 +468,8 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Blue);
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue);
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Blue);
|
||||
CRT_colors[PROCESS_THREAD] = ColorPair(Green,Blue);
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Blue);
|
||||
CRT_colors[BAR_BORDER] = A_BOLD | ColorPair(Yellow,Blue);
|
||||
CRT_colors[BAR_SHADOW] = ColorPair(Cyan,Blue);
|
||||
CRT_colors[SWAP] = ColorPair(Red,Blue);
|
||||
@ -406,22 +484,27 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue);
|
||||
CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,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[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue);
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue);
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White,Blue);
|
||||
CRT_colors[LOAD] = A_BOLD | ColorPair(White,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[CHECK_BOX] = ColorPair(Cyan,Blue);
|
||||
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(White,Blue);
|
||||
CRT_colors[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue);
|
||||
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Yellow,Blue);
|
||||
CRT_colors[HOSTNAME] = ColorPair(White,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_SOFTIRQ] = ColorPair(Black,Blue);
|
||||
CRT_colors[CPU_STEAL] = ColorPair(White,Blue);
|
||||
CRT_colors[CPU_GUEST] = ColorPair(White,Blue);
|
||||
} else if (CRT_colorScheme == COLORSCHEME_BLACKNIGHT) {
|
||||
CRT_colors[RESET_COLOR] = ColorPair(Cyan,Black);
|
||||
CRT_colors[DEFAULT_COLOR] = ColorPair(Cyan,Black);
|
||||
@ -433,6 +516,7 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
|
||||
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
|
||||
CRT_colors[UPTIME] = ColorPair(Green,Black);
|
||||
CRT_colors[BATTERY] = ColorPair(Green,Black);
|
||||
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black);
|
||||
CRT_colors[METER_TEXT] = ColorPair(Cyan,Black);
|
||||
CRT_colors[METER_VALUE] = ColorPair(Green,Black);
|
||||
@ -444,6 +528,8 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_BASENAME] = A_BOLD | ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_TREE] = ColorPair(Cyan,Black);
|
||||
CRT_colors[PROCESS_THREAD] = ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black);
|
||||
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
|
||||
@ -461,22 +547,27 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black);
|
||||
CRT_colors[MEMORY_USED] = ColorPair(Green,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[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black);
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black);
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green,Black);
|
||||
CRT_colors[LOAD] = A_BOLD;
|
||||
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] = ColorPair(Green,Black);
|
||||
CRT_colors[CHECK_BOX] = ColorPair(Green,Black);
|
||||
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,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_IRQ] = A_BOLD | 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 {
|
||||
/* Default */
|
||||
CRT_colors[RESET_COLOR] = ColorPair(White,Black);
|
||||
@ -489,6 +580,7 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
|
||||
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
|
||||
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[METER_TEXT] = ColorPair(Cyan,Black);
|
||||
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Black);
|
||||
@ -503,6 +595,8 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
|
||||
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
|
||||
CRT_colors[PROCESS_THREAD] = ColorPair(Green,Black);
|
||||
CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Black);
|
||||
CRT_colors[BAR_BORDER] = A_BOLD;
|
||||
CRT_colors[BAR_SHADOW] = A_BOLD | ColorPair(Black,Black);
|
||||
CRT_colors[SWAP] = ColorPair(Red,Black);
|
||||
@ -517,21 +611,26 @@ void CRT_setColors(int colorScheme) {
|
||||
CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black);
|
||||
CRT_colors[MEMORY_USED] = ColorPair(Green,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[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black);
|
||||
CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL;
|
||||
CRT_colors[LOAD_AVERAGE_ONE] = A_BOLD;
|
||||
CRT_colors[LOAD] = A_BOLD;
|
||||
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[CHECK_BOX] = ColorPair(Cyan,Black);
|
||||
CRT_colors[CHECK_MARK] = A_BOLD;
|
||||
CRT_colors[CHECK_TEXT] = A_NORMAL;
|
||||
CRT_colors[CPU_IOWAIT] = ColorPair(Cyan,Black);
|
||||
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_IRQ] = ColorPair(Yellow,Black);
|
||||
CRT_colors[CPU_SOFTIRQ] = ColorPair(Magenta,Black);
|
||||
CRT_colors[CPU_STEAL] = ColorPair(Cyan,Black);
|
||||
CRT_colors[CPU_GUEST] = ColorPair(Cyan,Black);
|
||||
}
|
||||
}
|
||||
|
45
CRT.h
45
CRT.h
@ -4,20 +4,13 @@
|
||||
#define HEADER_CRT
|
||||
/*
|
||||
htop - CRT.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
|
||||
#include <curses.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
#include "debug.h"
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
#endif
|
||||
|
||||
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
|
||||
|
||||
@ -39,8 +32,7 @@ in the source distribution for its full text.
|
||||
|
||||
//#link curses
|
||||
|
||||
bool CRT_hasColors;
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum ColorElements_ {
|
||||
RESET_COLOR,
|
||||
@ -57,7 +49,7 @@ typedef enum ColorElements_ {
|
||||
METER_VALUE,
|
||||
LED_COLOR,
|
||||
UPTIME,
|
||||
TASKS_TOTAL,
|
||||
BATTERY,
|
||||
TASKS_RUNNING,
|
||||
SWAP,
|
||||
PROCESS,
|
||||
@ -69,6 +61,8 @@ typedef enum ColorElements_ {
|
||||
PROCESS_BASENAME,
|
||||
PROCESS_HIGH_PRIORITY,
|
||||
PROCESS_LOW_PRIORITY,
|
||||
PROCESS_THREAD,
|
||||
PROCESS_THREAD_BASENAME,
|
||||
BAR_BORDER,
|
||||
BAR_SHADOW,
|
||||
GRAPH_1,
|
||||
@ -82,6 +76,7 @@ typedef enum ColorElements_ {
|
||||
GRAPH_9,
|
||||
MEMORY_USED,
|
||||
MEMORY_BUFFERS,
|
||||
MEMORY_BUFFERS_TEXT,
|
||||
MEMORY_CACHE,
|
||||
LOAD,
|
||||
LOAD_AVERAGE_FIFTEEN,
|
||||
@ -91,43 +86,53 @@ typedef enum ColorElements_ {
|
||||
CHECK_MARK,
|
||||
CHECK_TEXT,
|
||||
CLOCK,
|
||||
HELP_BOLD,
|
||||
HOSTNAME,
|
||||
CPU_NICE,
|
||||
CPU_NICE_TEXT,
|
||||
CPU_NORMAL,
|
||||
CPU_KERNEL,
|
||||
HELP_BOLD,
|
||||
CPU_IOWAIT,
|
||||
CPU_IRQ,
|
||||
CPU_SOFTIRQ,
|
||||
CPU_STEAL,
|
||||
CPU_GUEST,
|
||||
LAST_COLORELEMENT
|
||||
} ColorElements;
|
||||
|
||||
void CRT_fatalError(const char* note) __attribute__ ((noreturn));
|
||||
|
||||
|
||||
// TODO: centralize these in Settings.
|
||||
|
||||
extern int CRT_delay;
|
||||
|
||||
extern int CRT_colorScheme;
|
||||
|
||||
extern bool CRT_utf8;
|
||||
|
||||
extern int CRT_colors[LAST_COLORELEMENT];
|
||||
|
||||
extern int CRT_cursorX;
|
||||
|
||||
extern int CRT_scrollHAmount;
|
||||
|
||||
char* CRT_termType;
|
||||
|
||||
void *backtraceArray[128];
|
||||
|
||||
// TODO: pass an instance of Settings instead.
|
||||
|
||||
void CRT_init(int delay, int colorScheme);
|
||||
|
||||
void CRT_done();
|
||||
|
||||
void CRT_fatalError(const char* note);
|
||||
|
||||
int CRT_readKey();
|
||||
|
||||
void CRT_disableDelay();
|
||||
|
||||
void CRT_enableDelay();
|
||||
|
||||
void CRT_handleSIGSEGV(int signal);
|
||||
|
||||
void CRT_handleSIGTERM(int signal);
|
||||
|
||||
void CRT_setColors(int colorScheme);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,12 @@
|
||||
/*
|
||||
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 "AvailableMetersPanel.h"
|
||||
#include "MetersPanel.h"
|
||||
#include "DisplayOptionsPanel.h"
|
||||
@ -7,12 +14,13 @@
|
||||
#include "ColorsPanel.h"
|
||||
#include "AvailableColumnsPanel.h"
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct CategoriesPanel_ {
|
||||
Panel super;
|
||||
@ -23,59 +31,85 @@ typedef struct CategoriesPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
static char* MetersFunctions[10] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
|
||||
static const char* MetersFunctions[] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
|
||||
|
||||
static char* AvailableMetersFunctions[10] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done "};
|
||||
static const char* AvailableMetersFunctions[] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done ", NULL};
|
||||
|
||||
static char* DisplayOptionsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
|
||||
static const char* DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
|
||||
|
||||
static char* ColumnsFunctions[10] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
|
||||
static const char* ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
|
||||
|
||||
static char* ColorsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
|
||||
static const char* ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
|
||||
|
||||
static char* AvailableColumnsFunctions[10] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done "};
|
||||
static const char* AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL};
|
||||
|
||||
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
CategoriesPanel* this = (CategoriesPanel*) malloc(sizeof(CategoriesPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
|
||||
((Object*)this)->delete = CategoriesPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
super->eventHandler = CategoriesPanel_eventHandler;
|
||||
Panel_setHeader(super, "Setup");
|
||||
Panel_add(super, (Object*) ListItem_new("Meters", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Display options", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Colors", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Columns", 0));
|
||||
return this;
|
||||
}
|
||||
|
||||
void CategoriesPanel_delete(Object* object) {
|
||||
static void CategoriesPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
CategoriesPanel* this = (CategoriesPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||
void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
||||
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* 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, rightMeters, FunctionBar_new(MetersFunctions, NULL, NULL), 20);
|
||||
ScreenManager_add(this->scr, availableMeters, FunctionBar_new(AvailableMetersFunctions, NULL, NULL), -1);
|
||||
}
|
||||
|
||||
static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) {
|
||||
Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr);
|
||||
ScreenManager_add(this->scr, displayOptions, FunctionBar_new(DisplayOptionsFunctions, NULL, NULL), -1);
|
||||
}
|
||||
|
||||
static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
|
||||
Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr);
|
||||
ScreenManager_add(this->scr, colors, FunctionBar_new(ColorsFunctions, NULL, NULL), -1);
|
||||
}
|
||||
|
||||
static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
|
||||
Panel* columns = (Panel*) ColumnsPanel_new(this->settings, 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, availableColumns, FunctionBar_new(AvailableColumnsFunctions, NULL, NULL), -1);
|
||||
}
|
||||
|
||||
static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||
CategoriesPanel* this = (CategoriesPanel*) super;
|
||||
|
||||
HandlerResult result = IGNORED;
|
||||
|
||||
int previous = Panel_getSelectedIndex(super);
|
||||
|
||||
int selected = Panel_getSelectedIndex(super);
|
||||
switch (ch) {
|
||||
case EVENT_SETSELECTED:
|
||||
result = HANDLED;
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_CTRLP:
|
||||
case KEY_DOWN:
|
||||
case KEY_CTRLN:
|
||||
case KEY_NPAGE:
|
||||
case KEY_PPAGE:
|
||||
case KEY_HOME:
|
||||
case KEY_END: {
|
||||
int previous = selected;
|
||||
Panel_onKey(super, ch);
|
||||
int selected = Panel_getSelectedIndex(super);
|
||||
if (previous != selected) {
|
||||
selected = Panel_getSelectedIndex(super);
|
||||
if (previous != selected)
|
||||
result = HANDLED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (isalpha(ch))
|
||||
result = Panel_selectByTyping(super, ch);
|
||||
if (result == BREAK_LOOP)
|
||||
result = IGNORED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == HANDLED) {
|
||||
int size = ScreenManager_size(this->scr);
|
||||
for (int i = 1; i < size; i++)
|
||||
ScreenManager_remove(this->scr, 1);
|
||||
@ -94,35 +128,29 @@ HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
||||
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* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, leftMeters, rightMeters, this->scr);
|
||||
ScreenManager_add(this->scr, leftMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
|
||||
ScreenManager_add(this->scr, rightMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
|
||||
ScreenManager_add(this->scr, availableMeters, FunctionBar_new(10, AvailableMetersFunctions, NULL, NULL), -1);
|
||||
}
|
||||
PanelClass CategoriesPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = CategoriesPanel_delete
|
||||
},
|
||||
.eventHandler = CategoriesPanel_eventHandler
|
||||
};
|
||||
|
||||
void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) {
|
||||
Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr);
|
||||
ScreenManager_add(this->scr, displayOptions, FunctionBar_new(10, DisplayOptionsFunctions, NULL, NULL), -1);
|
||||
}
|
||||
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
CategoriesPanel* this = AllocThis(CategoriesPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true);
|
||||
|
||||
void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
|
||||
Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr);
|
||||
ScreenManager_add(this->scr, colors, FunctionBar_new(10, ColorsFunctions, NULL, NULL), -1);
|
||||
}
|
||||
|
||||
void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
|
||||
Panel* columns = (Panel*) ColumnsPanel_new(this->settings, this->scr);
|
||||
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(this->settings, columns, this->scr);
|
||||
ScreenManager_add(this->scr, columns, FunctionBar_new(10, ColumnsFunctions, NULL, NULL), 20);
|
||||
ScreenManager_add(this->scr, availableColumns, FunctionBar_new(10, AvailableColumnsFunctions, NULL, NULL), -1);
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
Panel_setHeader(super, "Setup");
|
||||
Panel_add(super, (Object*) ListItem_new("Meters", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Display options", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Colors", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Columns", 0));
|
||||
return this;
|
||||
}
|
||||
|
@ -2,19 +2,16 @@
|
||||
|
||||
#ifndef HEADER_CategoriesPanel
|
||||
#define HEADER_CategoriesPanel
|
||||
|
||||
#include "AvailableMetersPanel.h"
|
||||
#include "MetersPanel.h"
|
||||
#include "DisplayOptionsPanel.h"
|
||||
#include "ColumnsPanel.h"
|
||||
#include "ColorsPanel.h"
|
||||
#include "AvailableColumnsPanel.h"
|
||||
/*
|
||||
htop - CategoriesPanel.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 "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct CategoriesPanel_ {
|
||||
Panel super;
|
||||
@ -24,18 +21,10 @@ typedef struct CategoriesPanel_ {
|
||||
} CategoriesPanel;
|
||||
|
||||
|
||||
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
void CategoriesPanel_delete(Object* object);
|
||||
|
||||
HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch);
|
||||
|
||||
void CategoriesPanel_makeMetersPage(CategoriesPanel* this);
|
||||
|
||||
void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this);
|
||||
extern PanelClass CategoriesPanel_class;
|
||||
|
||||
void CategoriesPanel_makeColorsPage(CategoriesPanel* this);
|
||||
|
||||
void CategoriesPanel_makeColumnsPage(CategoriesPanel* this);
|
||||
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
#endif
|
||||
|
172
ChangeLog
172
ChangeLog
@ -1,3 +1,175 @@
|
||||
|
||||
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
|
||||
|
||||
* Ability to change sort column with the mouse by
|
||||
clicking column titles (click again to invert order)
|
||||
* Add support for Linux per-process IO statistics,
|
||||
enabled with the --enable-taskstats flag, which
|
||||
requires a kernel compiled with taskstats support.
|
||||
(thanks to Tobias Oetiker)
|
||||
* Add Unicode support, enabled with the --enable-unicode
|
||||
flag, which requires libncursesw.
|
||||
(thanks to Sergej Pupykin)
|
||||
* BUGFIX: Fix display of CPU count for threaded processes.
|
||||
When user threads are hidden, process now shows the
|
||||
sum of processor usage for all processors. When user
|
||||
threads are displayed, each thread shows its own
|
||||
processor usage, including the root thread.
|
||||
(thanks to Bert Wesarg for the report)
|
||||
* BUGFIX: avoid crashing when using many meters
|
||||
(thanks to David Cho for the report)
|
||||
|
||||
What's new in version 0.7
|
||||
|
||||
* CPU affinity configuration ('a' key)
|
||||
* Improve display of tree view, properly nesting
|
||||
threads of the same app based on TGID.
|
||||
* IO-wait time now counts as idle time, which is a more
|
||||
accurate description. It is still available in
|
||||
split time, now called detailed CPU time.
|
||||
(thanks to Samuel Thibault for the report)
|
||||
* BUGFIX: Correct display of TPGID field
|
||||
* Add TGID field
|
||||
* BUGFIX: Don't crash with invalid command-line flags
|
||||
(thanks to Nico Golde for the report)
|
||||
* Fix GCC 4.3 compilation issues
|
||||
(thanks to Martin Michlmayr for the report)
|
||||
* OpenVZ support, enabled at compile-time with
|
||||
the --enable-openvz flag.
|
||||
(thanks to Sergey Lychko)
|
||||
|
||||
What's new in version 0.6.6
|
||||
|
||||
* Add support of NLWP field
|
||||
|
62
CheckItem.c
62
CheckItem.c
@ -1,43 +1,30 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - CheckItem.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 "CheckItem.h"
|
||||
#include "Object.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*{
|
||||
#include "Object.h"
|
||||
|
||||
typedef struct CheckItem_ {
|
||||
Object super;
|
||||
char* text;
|
||||
bool* value;
|
||||
bool* ref;
|
||||
bool value;
|
||||
} CheckItem;
|
||||
|
||||
}*/
|
||||
|
||||
#ifdef DEBUG
|
||||
char* CHECKITEM_CLASS = "CheckItem";
|
||||
#else
|
||||
#define CHECKITEM_CLASS NULL
|
||||
#endif
|
||||
|
||||
CheckItem* CheckItem_new(char* text, bool* value) {
|
||||
CheckItem* this = malloc(sizeof(CheckItem));
|
||||
Object_setClass(this, CHECKITEM_CLASS);
|
||||
((Object*)this)->display = CheckItem_display;
|
||||
((Object*)this)->delete = CheckItem_delete;
|
||||
this->text = text;
|
||||
this->value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
void CheckItem_delete(Object* cast) {
|
||||
static void CheckItem_delete(Object* cast) {
|
||||
CheckItem* this = (CheckItem*)cast;
|
||||
assert (this != NULL);
|
||||
|
||||
@ -45,14 +32,41 @@ void CheckItem_delete(Object* cast) {
|
||||
free(this);
|
||||
}
|
||||
|
||||
void CheckItem_display(Object* cast, RichString* out) {
|
||||
static void CheckItem_display(Object* cast, RichString* out) {
|
||||
CheckItem* this = (CheckItem*)cast;
|
||||
assert (this != NULL);
|
||||
RichString_write(out, CRT_colors[CHECK_BOX], "[");
|
||||
if (*(this->value))
|
||||
if (CheckItem_get(this))
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], "x");
|
||||
else
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], " ");
|
||||
RichString_append(out, CRT_colors[CHECK_BOX], "] ");
|
||||
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* this = AllocThis(CheckItem);
|
||||
this->text = text;
|
||||
this->value = value;
|
||||
this->ref = ref;
|
||||
return this;
|
||||
}
|
||||
|
||||
void CheckItem_set(CheckItem* this, bool value) {
|
||||
if (this->ref)
|
||||
*(this->ref) = value;
|
||||
else
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
bool CheckItem_get(CheckItem* this) {
|
||||
if (this->ref)
|
||||
return *(this->ref);
|
||||
else
|
||||
return this->value;
|
||||
}
|
||||
|
23
CheckItem.h
23
CheckItem.h
@ -3,35 +3,28 @@
|
||||
#ifndef HEADER_CheckItem
|
||||
#define HEADER_CheckItem
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - CheckItem.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 "Object.h"
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
typedef struct CheckItem_ {
|
||||
Object super;
|
||||
char* text;
|
||||
bool* value;
|
||||
bool* ref;
|
||||
bool value;
|
||||
} CheckItem;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* CHECKITEM_CLASS;
|
||||
#else
|
||||
#define CHECKITEM_CLASS NULL
|
||||
#endif
|
||||
extern ObjectClass CheckItem_class;
|
||||
|
||||
CheckItem* CheckItem_new(char* text, bool* value);
|
||||
CheckItem* CheckItem_new(char* text, bool* ref, bool value);
|
||||
|
||||
void CheckItem_delete(Object* cast);
|
||||
void CheckItem_set(CheckItem* this, bool value);
|
||||
|
||||
void CheckItem_display(Object* cast, RichString* out);
|
||||
bool CheckItem_get(CheckItem* this);
|
||||
|
||||
#endif
|
||||
|
36
ClockMeter.c
36
ClockMeter.c
@ -1,36 +1,42 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - ClockMeter.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 "ClockMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "debug.h"
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
int ClockMeter_attributes[] = {
|
||||
CLOCK
|
||||
};
|
||||
|
||||
MeterType ClockMeter = {
|
||||
static void ClockMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
time_t t = time(NULL);
|
||||
struct tm result;
|
||||
struct tm *lt = localtime_r(&t, &result);
|
||||
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
|
||||
strftime(buffer, size, "%H:%M:%S", lt);
|
||||
}
|
||||
|
||||
MeterClass ClockMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete
|
||||
},
|
||||
.setValues = ClockMeter_setValues,
|
||||
.display = NULL,
|
||||
.mode = TEXT_METERMODE,
|
||||
.defaultMode = TEXT_METERMODE,
|
||||
.total = 100.0,
|
||||
.items = 1,
|
||||
.attributes = ClockMeter_attributes,
|
||||
.name = "Clock",
|
||||
.uiName = "Clock",
|
||||
.caption = "Time: ",
|
||||
};
|
||||
|
||||
void ClockMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
time_t t = time(NULL);
|
||||
struct tm *lt = localtime(&t);
|
||||
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
|
||||
strftime(buffer, size, "%H:%M:%S", lt);
|
||||
}
|
||||
|
12
ClockMeter.h
12
ClockMeter.h
@ -3,22 +3,16 @@
|
||||
#ifndef HEADER_ClockMeter
|
||||
#define HEADER_ClockMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - ClockMeter.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"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern int ClockMeter_attributes[];
|
||||
|
||||
extern MeterType ClockMeter;
|
||||
|
||||
void ClockMeter_setValues(Meter* this, char* buffer, int size);
|
||||
extern MeterClass ClockMeter_class;
|
||||
|
||||
#endif
|
||||
|
@ -1,14 +1,18 @@
|
||||
/*
|
||||
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 "CRT.h"
|
||||
#include "ColorsPanel.h"
|
||||
|
||||
#include "Panel.h"
|
||||
#include "CRT.h"
|
||||
#include "CheckItem.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// TO ADD A NEW SCHEME:
|
||||
// * Increment the size of bool check in ColorsPanel.h
|
||||
@ -17,18 +21,20 @@
|
||||
// * Add the colors in CRT_setColors
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct ColorsPanel_ {
|
||||
Panel super;
|
||||
|
||||
Settings* settings;
|
||||
ScreenManager* scr;
|
||||
bool check[5];
|
||||
} ColorsPanel;
|
||||
|
||||
}*/
|
||||
|
||||
static char* ColorSchemes[] = {
|
||||
static const char* ColorSchemes[] = {
|
||||
"Default",
|
||||
"Monochromatic",
|
||||
"Black on White",
|
||||
@ -38,33 +44,14 @@ static char* ColorSchemes[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
ColorsPanel* this = (ColorsPanel*) malloc(sizeof(ColorsPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
|
||||
((Object*)this)->delete = ColorsPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
super->eventHandler = ColorsPanel_EventHandler;
|
||||
|
||||
Panel_setHeader(super, "Colors");
|
||||
for (int i = 0; ColorSchemes[i] != NULL; i++) {
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy(ColorSchemes[i]), &(this->check[i])));
|
||||
this->check[i] = false;
|
||||
}
|
||||
this->check[settings->colorScheme] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
void ColorsPanel_delete(Object* object) {
|
||||
static void ColorsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
ColorsPanel* this = (ColorsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
|
||||
static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) {
|
||||
ColorsPanel* this = (ColorsPanel*) super;
|
||||
|
||||
HandlerResult result = IGNORED;
|
||||
@ -74,11 +61,11 @@ HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
|
||||
case 0x0a:
|
||||
case 0x0d:
|
||||
case KEY_ENTER:
|
||||
case KEY_MOUSE:
|
||||
case ' ':
|
||||
for (int i = 0; ColorSchemes[i] != NULL; i++) {
|
||||
this->check[i] = false;
|
||||
}
|
||||
this->check[mark] = true;
|
||||
for (int i = 0; ColorSchemes[i] != NULL; i++)
|
||||
CheckItem_set((CheckItem*)Panel_get(super, i), false);
|
||||
CheckItem_set((CheckItem*)Panel_get(super, mark), true);
|
||||
this->settings->colorScheme = mark;
|
||||
result = HANDLED;
|
||||
}
|
||||
@ -87,7 +74,7 @@ HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
|
||||
this->settings->changed = true;
|
||||
Header* header = this->settings->header;
|
||||
CRT_setColors(mark);
|
||||
Panel* menu = (Panel*) Vector_get(this->scr->items, 0);
|
||||
Panel* menu = (Panel*) Vector_get(this->scr->panels, 0);
|
||||
Header_draw(header);
|
||||
RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]);
|
||||
RichString_setAttr(&(menu->header), CRT_colors[PANEL_HEADER_UNFOCUS]);
|
||||
@ -96,3 +83,26 @@ HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PanelClass ColorsPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = ColorsPanel_delete
|
||||
},
|
||||
.eventHandler = ColorsPanel_eventHandler
|
||||
};
|
||||
|
||||
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
ColorsPanel* this = AllocThis(ColorsPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
|
||||
Panel_setHeader(super, "Colors");
|
||||
for (int i = 0; ColorSchemes[i] != NULL; i++) {
|
||||
Panel_add(super, (Object*) CheckItem_new(strdup(ColorSchemes[i]), NULL, false));
|
||||
}
|
||||
CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true);
|
||||
return this;
|
||||
}
|
||||
|
@ -2,16 +2,12 @@
|
||||
|
||||
#ifndef HEADER_ColorsPanel
|
||||
#define HEADER_ColorsPanel
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "Panel.h"
|
||||
#include "CheckItem.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
/*
|
||||
htop - ColorsPanel.h
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
// TO ADD A NEW SCHEME:
|
||||
// * Increment the size of bool check in ColorsPanel.h
|
||||
@ -19,21 +15,20 @@
|
||||
// * Add a define in CRT.h that matches the order of the array
|
||||
// * Add the colors in CRT_setColors
|
||||
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct ColorsPanel_ {
|
||||
Panel super;
|
||||
|
||||
Settings* settings;
|
||||
ScreenManager* scr;
|
||||
bool check[5];
|
||||
} ColorsPanel;
|
||||
|
||||
|
||||
extern PanelClass ColorsPanel_class;
|
||||
|
||||
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
void ColorsPanel_delete(Object* object);
|
||||
|
||||
HandlerResult ColorsPanel_EventHandler(Panel* super, int ch);
|
||||
|
||||
|
||||
#endif
|
||||
|
128
ColumnsPanel.c
128
ColumnsPanel.c
@ -1,15 +1,23 @@
|
||||
/*
|
||||
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 "String.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*{
|
||||
|
||||
typedef struct ColumnsPanel_ {
|
||||
Panel super;
|
||||
|
||||
@ -19,61 +27,18 @@ typedef struct ColumnsPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
ColumnsPanel* this = (ColumnsPanel*) malloc(sizeof(ColumnsPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
|
||||
((Object*)this)->delete = ColumnsPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
super->eventHandler = ColumnsPanel_eventHandler;
|
||||
Panel_setHeader(super, "Active Columns");
|
||||
|
||||
ProcessField* fields = this->settings->pl->fields;
|
||||
for (; *fields; fields++) {
|
||||
Panel_add(super, (Object*) ListItem_new(Process_fieldNames[*fields], 0));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void ColumnsPanel_delete(Object* object) {
|
||||
static void ColumnsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
ColumnsPanel* this = (ColumnsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
int ColumnsPanel_fieldNameToIndex(const char* name) {
|
||||
for (int j = 1; j <= LAST_PROCESSFIELD; j++) {
|
||||
if (String_eq(name, Process_fieldNames[j])) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ColumnsPanel_update(Panel* super) {
|
||||
ColumnsPanel* this = (ColumnsPanel*) super;
|
||||
int size = Panel_getSize(super);
|
||||
this->settings->changed = true;
|
||||
// FIXME: this is crappily inefficient
|
||||
free(this->settings->pl->fields);
|
||||
this->settings->pl->fields = (ProcessField*) malloc(sizeof(ProcessField) * (size+1));
|
||||
for (int i = 0; i < size; i++) {
|
||||
char* text = ((ListItem*) Panel_get(super, i))->value;
|
||||
int j = ColumnsPanel_fieldNameToIndex(text);
|
||||
if (j > 0)
|
||||
this->settings->pl->fields[i] = j;
|
||||
}
|
||||
this->settings->pl->fields[size] = 0;
|
||||
}
|
||||
|
||||
HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||
static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||
|
||||
int selected = Panel_getSelectedIndex(super);
|
||||
HandlerResult result = IGNORED;
|
||||
int size = Panel_getSize(super);
|
||||
int size = Panel_size(super);
|
||||
|
||||
switch(ch) {
|
||||
case KEY_F(7):
|
||||
@ -103,8 +68,69 @@ HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||
result = HANDLED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (isalpha(ch))
|
||||
result = Panel_selectByTyping(super, ch);
|
||||
if (result == BREAK_LOOP)
|
||||
result = IGNORED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == HANDLED)
|
||||
ColumnsPanel_update(super);
|
||||
return result;
|
||||
}
|
||||
|
||||
PanelClass ColumnsPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = ColumnsPanel_delete
|
||||
},
|
||||
.eventHandler = ColumnsPanel_eventHandler
|
||||
};
|
||||
|
||||
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
ColumnsPanel* this = AllocThis(ColumnsPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
Panel_setHeader(super, "Active Columns");
|
||||
|
||||
ProcessField* fields = this->settings->pl->fields;
|
||||
for (; *fields; fields++) {
|
||||
Panel_add(super, (Object*) ListItem_new(Process_fieldNames[*fields], 0));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
int ColumnsPanel_fieldNameToIndex(const char* name) {
|
||||
for (int j = 1; j <= LAST_PROCESSFIELD; j++) {
|
||||
if (String_eq(name, Process_fieldNames[j])) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ColumnsPanel_update(Panel* super) {
|
||||
ColumnsPanel* this = (ColumnsPanel*) super;
|
||||
int size = Panel_size(super);
|
||||
this->settings->changed = true;
|
||||
// FIXME: this is crappily inefficient
|
||||
free(this->settings->pl->fields);
|
||||
this->settings->pl->fields = (ProcessField*) malloc(sizeof(ProcessField) * (size+1));
|
||||
this->settings->pl->flags = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
char* text = ((ListItem*) Panel_get(super, i))->value;
|
||||
int j = ColumnsPanel_fieldNameToIndex(text);
|
||||
if (j > 0) {
|
||||
this->settings->pl->fields[i] = j;
|
||||
this->settings->pl->flags |= Process_fieldFlags[j];
|
||||
}
|
||||
}
|
||||
this->settings->pl->fields[size] = 0;
|
||||
}
|
||||
|
||||
|
@ -2,16 +2,17 @@
|
||||
|
||||
#ifndef 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 "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
typedef struct ColumnsPanel_ {
|
||||
Panel super;
|
||||
|
||||
@ -20,14 +21,13 @@ typedef struct ColumnsPanel_ {
|
||||
} ColumnsPanel;
|
||||
|
||||
|
||||
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr);
|
||||
extern PanelClass ColumnsPanel_class;
|
||||
|
||||
void ColumnsPanel_delete(Object* object);
|
||||
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
int ColumnsPanel_fieldNameToIndex(const char* name);
|
||||
|
||||
void ColumnsPanel_update(Panel* super);
|
||||
|
||||
HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch);
|
||||
|
||||
#endif
|
||||
|
227
DebugMemory.c
227
DebugMemory.c
@ -1,227 +0,0 @@
|
||||
|
||||
#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
|
@ -1,71 +0,0 @@
|
||||
/* 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
|
@ -1,15 +1,22 @@
|
||||
/*
|
||||
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 "Panel.h"
|
||||
#include "CheckItem.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct DisplayOptionsPanel_ {
|
||||
Panel super;
|
||||
@ -20,36 +27,14 @@ typedef struct DisplayOptionsPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
DisplayOptionsPanel* this = (DisplayOptionsPanel*) malloc(sizeof(DisplayOptionsPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
|
||||
((Object*)this)->delete = DisplayOptionsPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
super->eventHandler = DisplayOptionsPanel_EventHandler;
|
||||
|
||||
Panel_setHeader(super, "Display options");
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Tree view"), &(settings->pl->treeView)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin)));
|
||||
Panel_add(super, (Object*) CheckItem_new(String_copy("Split System Time into System/IO-Wait/Hard-IRQ/Soft-IRQ"), &(settings->pl->expandSystemTime)));
|
||||
return this;
|
||||
}
|
||||
|
||||
void DisplayOptionsPanel_delete(Object* object) {
|
||||
static void DisplayOptionsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
DisplayOptionsPanel* this = (DisplayOptionsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
HandlerResult DisplayOptionsPanel_EventHandler(Panel* super, int ch) {
|
||||
static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
|
||||
DisplayOptionsPanel* this = (DisplayOptionsPanel*) super;
|
||||
|
||||
HandlerResult result = IGNORED;
|
||||
@ -59,8 +44,9 @@ HandlerResult DisplayOptionsPanel_EventHandler(Panel* super, int ch) {
|
||||
case 0x0a:
|
||||
case 0x0d:
|
||||
case KEY_ENTER:
|
||||
case KEY_MOUSE:
|
||||
case ' ':
|
||||
*(selected->value) = ! *(selected->value);
|
||||
CheckItem_set(selected, ! (CheckItem_get(selected)) );
|
||||
result = HANDLED;
|
||||
}
|
||||
|
||||
@ -68,9 +54,42 @@ HandlerResult DisplayOptionsPanel_EventHandler(Panel* super, int ch) {
|
||||
this->settings->changed = true;
|
||||
Header* header = this->settings->header;
|
||||
Header_calculateHeight(header);
|
||||
Header_reinit(header);
|
||||
Header_draw(header);
|
||||
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PanelClass DisplayOptionsPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = DisplayOptionsPanel_delete
|
||||
},
|
||||
.eventHandler = DisplayOptionsPanel_eventHandler
|
||||
};
|
||||
|
||||
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
DisplayOptionsPanel* this = AllocThis(DisplayOptionsPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->scr = scr;
|
||||
|
||||
Panel_setHeader(super, "Display options");
|
||||
Panel_add(super, (Object*) CheckItem_new(strdup("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(strdup("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(strdup("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(strdup("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false));
|
||||
Panel_add(super, (Object*) CheckItem_new(strdup("Highlight large numbers in memory counters"), &(settings->pl->highlightMegabytes), false));
|
||||
Panel_add(super, (Object*) CheckItem_new(strdup("Leave a margin around header"), &(settings->header->margin), 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;
|
||||
}
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
#ifndef 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 "CheckItem.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
typedef struct DisplayOptionsPanel_ {
|
||||
Panel super;
|
||||
|
||||
@ -21,11 +21,8 @@ typedef struct DisplayOptionsPanel_ {
|
||||
} DisplayOptionsPanel;
|
||||
|
||||
|
||||
extern PanelClass DisplayOptionsPanel_class;
|
||||
|
||||
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
void DisplayOptionsPanel_delete(Object* object);
|
||||
|
||||
HandlerResult DisplayOptionsPanel_EventHandler(Panel* super, int ch);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,23 +1,21 @@
|
||||
/*
|
||||
htop - FunctionBar.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Object.h"
|
||||
#include "FunctionBar.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <curses.h>
|
||||
|
||||
/*{
|
||||
#include "Object.h"
|
||||
|
||||
typedef struct FunctionBar_ {
|
||||
Object super;
|
||||
@ -30,74 +28,76 @@ typedef struct FunctionBar_ {
|
||||
|
||||
}*/
|
||||
|
||||
#ifdef DEBUG
|
||||
char* FUNCTIONBAR_CLASS = "FunctionBar";
|
||||
#else
|
||||
#define FUNCTIONBAR_CLASS NULL
|
||||
#endif
|
||||
static const char* FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL};
|
||||
|
||||
static char* FunctionBar_FKeys[10] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"};
|
||||
static const char* FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL};
|
||||
|
||||
static char* FunctionBar_FLabels[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
|
||||
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 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)};
|
||||
ObjectClass FunctionBar_class = {
|
||||
.delete = FunctionBar_delete
|
||||
};
|
||||
|
||||
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) {
|
||||
FunctionBar* this = malloc(sizeof(FunctionBar));
|
||||
Object_setClass(this, FUNCTIONBAR_CLASS);
|
||||
((Object*) this)->delete = FunctionBar_delete;
|
||||
this->functions = functions;
|
||||
this->size = size;
|
||||
FunctionBar* FunctionBar_new(const char** functions, const char** keys, int* events) {
|
||||
FunctionBar* this = AllocThis(FunctionBar);
|
||||
this->functions = calloc(16, sizeof(char*));
|
||||
if (!functions) {
|
||||
functions = FunctionBar_FLabels;
|
||||
}
|
||||
for (int i = 0; i < 15 && functions[i]; i++) {
|
||||
this->functions[i] = strdup(functions[i]);
|
||||
}
|
||||
if (keys && events) {
|
||||
this->staticData = false;
|
||||
this->functions = malloc(sizeof(char*) * size);
|
||||
this->keys = malloc(sizeof(char*) * size);
|
||||
this->events = malloc(sizeof(int) * size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
this->functions[i] = String_copy(functions[i]);
|
||||
this->keys[i] = String_copy(keys[i]);
|
||||
this->keys = malloc(sizeof(char*) * 15);
|
||||
this->events = malloc(sizeof(int) * 15);
|
||||
int i = 0;
|
||||
while (i < 15 && functions[i]) {
|
||||
this->keys[i] = strdup(keys[i]);
|
||||
this->events[i] = events[i];
|
||||
i++;
|
||||
}
|
||||
this->size = i;
|
||||
} else {
|
||||
this->staticData = true;
|
||||
this->functions = functions ? functions : FunctionBar_FLabels;
|
||||
this->keys = FunctionBar_FKeys;
|
||||
this->keys = (char**) FunctionBar_FKeys;
|
||||
this->events = FunctionBar_FEvents;
|
||||
assert((!functions) || this->size == 10);
|
||||
this->size = 10;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void FunctionBar_delete(Object* cast) {
|
||||
FunctionBar* this = (FunctionBar*) cast;
|
||||
if (!this->staticData) {
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
for (int i = 0; i < 15 && this->functions[i]; i++) {
|
||||
free(this->functions[i]);
|
||||
free(this->keys[i]);
|
||||
}
|
||||
free(this->functions);
|
||||
if (!this->staticData) {
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
free(this->keys[i]);
|
||||
}
|
||||
free(this->keys);
|
||||
free(this->events);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
void FunctionBar_setLabel(FunctionBar* this, int event, char* text) {
|
||||
assert(!this->staticData);
|
||||
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) {
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
if (this->events[i] == event) {
|
||||
free(this->functions[i]);
|
||||
this->functions[i] = String_copy(text);
|
||||
this->functions[i] = strdup(text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FunctionBar_draw(FunctionBar* this, char* buffer) {
|
||||
void FunctionBar_draw(const FunctionBar* this, char* buffer) {
|
||||
FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]);
|
||||
}
|
||||
|
||||
void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr) {
|
||||
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) {
|
||||
attrset(CRT_colors[FUNCTION_BAR]);
|
||||
mvhline(LINES-1, 0, ' ', COLS);
|
||||
int x = 0;
|
||||
@ -109,14 +109,18 @@ void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr) {
|
||||
mvaddstr(LINES-1, x, this->functions[i]);
|
||||
x += strlen(this->functions[i]);
|
||||
}
|
||||
if (buffer != NULL) {
|
||||
if (buffer) {
|
||||
attrset(attr);
|
||||
mvaddstr(LINES-1, x, buffer);
|
||||
CRT_cursorX = x + strlen(buffer);
|
||||
curs_set(1);
|
||||
} else {
|
||||
curs_set(0);
|
||||
}
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
}
|
||||
|
||||
int FunctionBar_synthesizeEvent(FunctionBar* this, int pos) {
|
||||
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) {
|
||||
int x = 0;
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
x += strlen(this->keys[i]);
|
||||
|
@ -4,22 +4,12 @@
|
||||
#define HEADER_FunctionBar
|
||||
/*
|
||||
htop - FunctionBar.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#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_ {
|
||||
Object super;
|
||||
@ -31,22 +21,18 @@ typedef struct FunctionBar_ {
|
||||
} FunctionBar;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* FUNCTIONBAR_CLASS;
|
||||
#else
|
||||
#define FUNCTIONBAR_CLASS NULL
|
||||
#endif
|
||||
extern ObjectClass FunctionBar_class;
|
||||
|
||||
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events);
|
||||
FunctionBar* FunctionBar_new(const char** functions, const char** keys, int* events);
|
||||
|
||||
void FunctionBar_delete(Object* cast);
|
||||
|
||||
void FunctionBar_setLabel(FunctionBar* this, int event, char* text);
|
||||
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text);
|
||||
|
||||
void FunctionBar_draw(FunctionBar* this, char* buffer);
|
||||
void FunctionBar_draw(const FunctionBar* this, char* buffer);
|
||||
|
||||
void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr);
|
||||
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr);
|
||||
|
||||
int FunctionBar_synthesizeEvent(FunctionBar* this, int pos);
|
||||
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos);
|
||||
|
||||
#endif
|
||||
|
20
Hashtable.c
20
Hashtable.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Hashtable.c
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
@ -8,12 +8,11 @@ in the source distribution for its full text.
|
||||
#include "Hashtable.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/*{
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct Hashtable_ Hashtable;
|
||||
|
||||
typedef void(*Hashtable_PairFunction)(int, void*, void*);
|
||||
@ -34,7 +33,7 @@ struct Hashtable_ {
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
bool Hashtable_isConsistent(Hashtable* this) {
|
||||
static bool Hashtable_isConsistent(Hashtable* this) {
|
||||
int items = 0;
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
HashtableItem* bucket = this->buckets[i];
|
||||
@ -61,7 +60,7 @@ int Hashtable_count(Hashtable* this) {
|
||||
|
||||
#endif
|
||||
|
||||
HashtableItem* HashtableItem_new(unsigned int key, void* value) {
|
||||
static HashtableItem* HashtableItem_new(unsigned int key, void* value) {
|
||||
HashtableItem* this;
|
||||
|
||||
this = (HashtableItem*) malloc(sizeof(HashtableItem));
|
||||
@ -77,7 +76,7 @@ Hashtable* Hashtable_new(int size, bool owner) {
|
||||
this = (Hashtable*) malloc(sizeof(Hashtable));
|
||||
this->items = 0;
|
||||
this->size = size;
|
||||
this->buckets = (HashtableItem**) calloc(sizeof(HashtableItem*), size);
|
||||
this->buckets = (HashtableItem**) calloc(size, sizeof(HashtableItem*));
|
||||
this->owner = owner;
|
||||
assert(Hashtable_isConsistent(this));
|
||||
return this;
|
||||
@ -99,11 +98,6 @@ void Hashtable_delete(Hashtable* this) {
|
||||
free(this);
|
||||
}
|
||||
|
||||
inline int Hashtable_size(Hashtable* this) {
|
||||
assert(Hashtable_isConsistent(this));
|
||||
return this->items;
|
||||
}
|
||||
|
||||
void Hashtable_put(Hashtable* this, unsigned int key, void* value) {
|
||||
unsigned int index = key % this->size;
|
||||
HashtableItem** bucketPtr = &(this->buckets[index]);
|
||||
|
17
Hashtable.h
17
Hashtable.h
@ -3,18 +3,13 @@
|
||||
#ifndef HEADER_Hashtable
|
||||
#define HEADER_Hashtable
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Hashtable.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 <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct Hashtable_ Hashtable;
|
||||
|
||||
@ -35,25 +30,19 @@ struct Hashtable_ {
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
bool Hashtable_isConsistent(Hashtable* this);
|
||||
|
||||
int Hashtable_count(Hashtable* this);
|
||||
|
||||
#endif
|
||||
|
||||
HashtableItem* HashtableItem_new(unsigned int key, void* value);
|
||||
|
||||
Hashtable* Hashtable_new(int size, bool owner);
|
||||
|
||||
void Hashtable_delete(Hashtable* this);
|
||||
|
||||
inline int Hashtable_size(Hashtable* this);
|
||||
|
||||
void Hashtable_put(Hashtable* this, unsigned int key, void* value);
|
||||
|
||||
void* Hashtable_remove(Hashtable* this, unsigned int key);
|
||||
|
||||
inline void* Hashtable_get(Hashtable* this, unsigned int key);
|
||||
extern void* Hashtable_get(Hashtable* this, unsigned int key);
|
||||
|
||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
||||
|
||||
|
79
Header.c
79
Header.c
@ -1,17 +1,32 @@
|
||||
/*
|
||||
htop - Header.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Header.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "CRT.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 <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*{
|
||||
#include "ProcessList.h"
|
||||
#include "Meter.h"
|
||||
|
||||
typedef enum HeaderSide_ {
|
||||
LEFT_HEADER,
|
||||
@ -22,9 +37,9 @@ typedef struct Header_ {
|
||||
Vector* leftMeters;
|
||||
Vector* rightMeters;
|
||||
ProcessList* pl;
|
||||
bool margin;
|
||||
int height;
|
||||
int pad;
|
||||
bool margin;
|
||||
} Header;
|
||||
|
||||
}*/
|
||||
@ -34,9 +49,9 @@ typedef struct Header_ {
|
||||
#endif
|
||||
|
||||
Header* Header_new(ProcessList* pl) {
|
||||
Header* this = malloc(sizeof(Header));
|
||||
this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
|
||||
this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
|
||||
Header* this = calloc(1, sizeof(Header));
|
||||
this->leftMeters = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
||||
this->rightMeters = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
||||
this->margin = true;
|
||||
this->pl = pl;
|
||||
return this;
|
||||
@ -56,11 +71,11 @@ void Header_createMeter(Header* this, char* name, HeaderSide side) {
|
||||
char* paren = strchr(name, '(');
|
||||
int param = 0;
|
||||
if (paren) {
|
||||
int ok = sscanf(paren, "(%d)", ¶m);
|
||||
int ok = sscanf(paren, "(%10d)", ¶m);
|
||||
if (!ok) param = 0;
|
||||
*paren = '\0';
|
||||
}
|
||||
for (MeterType** type = Meter_types; *type; type++) {
|
||||
for (MeterClass** type = Meter_types; *type; type++) {
|
||||
if (String_eq(name, (*type)->name)) {
|
||||
Vector_add(meters, Meter_new(this->pl, param, *type));
|
||||
break;
|
||||
@ -73,11 +88,13 @@ void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side) {
|
||||
? this->leftMeters
|
||||
: this->rightMeters;
|
||||
|
||||
if (i >= Vector_size(meters))
|
||||
return;
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
Meter_setMode(meter, mode);
|
||||
}
|
||||
|
||||
Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side) {
|
||||
Meter* Header_addMeter(Header* this, MeterClass* type, int param, HeaderSide side) {
|
||||
Vector* meters = side == LEFT_HEADER
|
||||
? this->leftMeters
|
||||
: this->rightMeters;
|
||||
@ -101,10 +118,10 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side) {
|
||||
: this->rightMeters;
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
|
||||
int nameLen = strlen(meter->type->name);
|
||||
int nameLen = strlen(Meter_name(meter));
|
||||
int len = nameLen + 100;
|
||||
char* name = malloc(len);
|
||||
strncpy(name, meter->type->name, nameLen);
|
||||
strncpy(name, Meter_name(meter), nameLen);
|
||||
name[nameLen] = '\0';
|
||||
if (meter->param)
|
||||
snprintf(name + nameLen, len - nameLen, "(%d)", meter->param);
|
||||
@ -121,19 +138,39 @@ MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) {
|
||||
return meter->mode;
|
||||
}
|
||||
|
||||
void Header_defaultMeters(Header* this) {
|
||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
|
||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
|
||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
|
||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
|
||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &LoadAverageMeter));
|
||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &UptimeMeter));
|
||||
void Header_defaultMeters(Header* this, int cpuCount) {
|
||||
if (cpuCount > 8) {
|
||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(LeftCPUs2Meter)));
|
||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(RightCPUs2Meter)));
|
||||
} else if (cpuCount > 4) {
|
||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, (MeterClass*) Class(LeftCPUsMeter)));
|
||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, (MeterClass*) Class(RightCPUsMeter)));
|
||||
} 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_draw(Header* this) {
|
||||
void Header_reinit(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 pad = this->pad;
|
||||
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
for (int y = 0; y < height; y++) {
|
||||
mvhline(y, 0, ' ', COLS);
|
||||
|
17
Header.h
17
Header.h
@ -4,17 +4,14 @@
|
||||
#define HEADER_Header
|
||||
/*
|
||||
htop - Header.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "ProcessList.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
typedef enum HeaderSide_ {
|
||||
LEFT_HEADER,
|
||||
RIGHT_HEADER
|
||||
@ -24,9 +21,9 @@ typedef struct Header_ {
|
||||
Vector* leftMeters;
|
||||
Vector* rightMeters;
|
||||
ProcessList* pl;
|
||||
bool margin;
|
||||
int height;
|
||||
int pad;
|
||||
bool margin;
|
||||
} Header;
|
||||
|
||||
|
||||
@ -42,7 +39,7 @@ void Header_createMeter(Header* this, char* name, HeaderSide side);
|
||||
|
||||
void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side);
|
||||
|
||||
Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side);
|
||||
Meter* Header_addMeter(Header* this, MeterClass* type, int param, HeaderSide side);
|
||||
|
||||
int Header_size(Header* this, HeaderSide side);
|
||||
|
||||
@ -50,9 +47,11 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side);
|
||||
|
||||
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side);
|
||||
|
||||
void Header_defaultMeters(Header* this);
|
||||
void Header_defaultMeters(Header* this, int cpuCount);
|
||||
|
||||
void Header_draw(Header* this);
|
||||
void Header_reinit(Header* this);
|
||||
|
||||
void Header_draw(const Header* this);
|
||||
|
||||
int Header_calculateHeight(Header* this);
|
||||
|
||||
|
39
HostnameMeter.c
Normal file
39
HostnameMeter.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
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: ",
|
||||
};
|
18
HostnameMeter.h
Normal file
18
HostnameMeter.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* 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
|
41
IOPriority.c
Normal file
41
IOPriority.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
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)
|
||||
|
||||
}*/
|
||||
|
43
IOPriority.h
Normal file
43
IOPriority.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* 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
|
43
IOPriorityPanel.c
Normal file
43
IOPriorityPanel.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 );
|
||||
}
|
20
IOPriorityPanel.h
Normal file
20
IOPriorityPanel.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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
Normal file
213
IncSet.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
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);
|
||||
}
|
56
IncSet.h
Normal file
56
IncSet.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* 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
|
68
ListItem.c
68
ListItem.c
@ -1,19 +1,22 @@
|
||||
/*
|
||||
htop - ListItem.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "ListItem.h"
|
||||
#include "String.h"
|
||||
#include "Object.h"
|
||||
#include "RichString.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "CRT.h"
|
||||
#include "String.h"
|
||||
#include "RichString.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*{
|
||||
#include "Object.h"
|
||||
|
||||
typedef struct ListItem_ {
|
||||
Object super;
|
||||
@ -23,42 +26,43 @@ typedef struct ListItem_ {
|
||||
|
||||
}*/
|
||||
|
||||
#ifdef DEBUG
|
||||
char* LISTITEM_CLASS = "ListItem";
|
||||
#else
|
||||
#define LISTITEM_CLASS NULL
|
||||
#endif
|
||||
|
||||
ListItem* ListItem_new(char* value, int key) {
|
||||
ListItem* this = malloc(sizeof(ListItem));
|
||||
Object_setClass(this, LISTITEM_CLASS);
|
||||
((Object*)this)->display = ListItem_display;
|
||||
((Object*)this)->delete = ListItem_delete;
|
||||
this->value = String_copy(value);
|
||||
this->key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
void ListItem_append(ListItem* this, char* text) {
|
||||
char* buf = malloc(strlen(this->value) + strlen(text) + 1);
|
||||
sprintf(buf, "%s%s", this->value, text);
|
||||
free(this->value);
|
||||
this->value = buf;
|
||||
}
|
||||
|
||||
void ListItem_delete(Object* cast) {
|
||||
static void ListItem_delete(Object* cast) {
|
||||
ListItem* this = (ListItem*)cast;
|
||||
free(this->value);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void ListItem_display(Object* cast, RichString* out) {
|
||||
static void ListItem_display(Object* cast, RichString* out) {
|
||||
ListItem* this = (ListItem*)cast;
|
||||
assert (this != NULL);
|
||||
/*
|
||||
int len = strlen(this->value)+1;
|
||||
char buffer[len+1];
|
||||
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 = {
|
||||
.display = ListItem_display,
|
||||
.delete = ListItem_delete,
|
||||
.compare = ListItem_compare
|
||||
};
|
||||
|
||||
ListItem* ListItem_new(const char* value, int key) {
|
||||
ListItem* this = AllocThis(ListItem);
|
||||
this->value = strdup(value);
|
||||
this->key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
void ListItem_append(ListItem* this, const char* text) {
|
||||
int oldLen = strlen(this->value);
|
||||
int textLen = strlen(text);
|
||||
int newLen = strlen(this->value) + textLen;
|
||||
this->value = realloc(this->value, newLen + 1);
|
||||
memcpy(this->value + oldLen, text, textLen);
|
||||
this->value[newLen] = '\0';
|
||||
}
|
||||
|
||||
const char* ListItem_getRef(ListItem* this) {
|
||||
|
22
ListItem.h
22
ListItem.h
@ -4,18 +4,12 @@
|
||||
#define HEADER_ListItem
|
||||
/*
|
||||
htop - ListItem.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 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"
|
||||
|
||||
|
||||
typedef struct ListItem_ {
|
||||
Object super;
|
||||
@ -24,19 +18,11 @@ typedef struct ListItem_ {
|
||||
} ListItem;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* LISTITEM_CLASS;
|
||||
#else
|
||||
#define LISTITEM_CLASS NULL
|
||||
#endif
|
||||
extern ObjectClass ListItem_class;
|
||||
|
||||
ListItem* ListItem_new(char* value, int key);
|
||||
ListItem* ListItem_new(const char* value, int key);
|
||||
|
||||
void ListItem_append(ListItem* this, char* text);
|
||||
|
||||
void ListItem_delete(Object* cast);
|
||||
|
||||
void ListItem_display(Object* cast, RichString* out);
|
||||
void ListItem_append(ListItem* this, const char* text);
|
||||
|
||||
const char* ListItem_getRef(ListItem* this);
|
||||
|
||||
|
@ -1,75 +1,56 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - LoadAverageMeter.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 "LoadAverageMeter.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
#include "debug.h"
|
||||
}*/
|
||||
|
||||
int LoadAverageMeter_attributes[] = {
|
||||
LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE
|
||||
};
|
||||
|
||||
MeterType LoadAverageMeter = {
|
||||
.setValues = LoadAverageMeter_setValues,
|
||||
.display = LoadAverageMeter_display,
|
||||
.mode = TEXT_METERMODE,
|
||||
.items = 3,
|
||||
.total = 100.0,
|
||||
.attributes = LoadAverageMeter_attributes,
|
||||
.name = "LoadAverage",
|
||||
.uiName = "Load average",
|
||||
.caption = "Load average: "
|
||||
};
|
||||
|
||||
int LoadMeter_attributes[] = { LOAD };
|
||||
|
||||
MeterType LoadMeter = {
|
||||
.setValues = LoadMeter_setValues,
|
||||
.display = LoadMeter_display,
|
||||
.mode = TEXT_METERMODE,
|
||||
.items = 1,
|
||||
.total = 100.0,
|
||||
.attributes = LoadMeter_attributes,
|
||||
.name = "Load",
|
||||
.uiName = "Load",
|
||||
.caption = "Load: "
|
||||
};
|
||||
|
||||
static inline void LoadAverageMeter_scan(double* one, double* five, double* fifteen) {
|
||||
int activeProcs, totalProcs, lastProc;
|
||||
*one = 0; *five = 0; *fifteen = 0;
|
||||
FILE *fd = fopen(PROCDIR "/loadavg", "r");
|
||||
int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
|
||||
if (fd) {
|
||||
int total = fscanf(fd, "%32lf %32lf %32lf %32d/%32d %32d", one, five, fifteen,
|
||||
&activeProcs, &totalProcs, &lastProc);
|
||||
(void) read;
|
||||
assert(read == 6);
|
||||
(void) total;
|
||||
assert(total == 6);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
snprintf(buffer, size, "%.2f/%.2f/%.2f", this->values[2], this->values[1], this->values[0]);
|
||||
}
|
||||
|
||||
void LoadAverageMeter_display(Object* cast, RichString* out) {
|
||||
static void LoadAverageMeter_display(Object* cast, RichString* out) {
|
||||
Meter* this = (Meter*)cast;
|
||||
char buffer[20];
|
||||
RichString_init(out);
|
||||
sprintf(buffer, "%.2f ", this->values[2]);
|
||||
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
|
||||
RichString_write(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
|
||||
sprintf(buffer, "%.2f ", this->values[1]);
|
||||
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer);
|
||||
sprintf(buffer, "%.2f ", this->values[0]);
|
||||
RichString_append(out, CRT_colors[LOAD_AVERAGE_ONE], buffer);
|
||||
}
|
||||
|
||||
void LoadMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
static void LoadMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
double five, fifteen;
|
||||
LoadAverageMeter_scan(&this->values[0], &five, &fifteen);
|
||||
if (this->values[0] > this->total) {
|
||||
@ -78,10 +59,40 @@ void LoadMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
snprintf(buffer, size, "%.2f", this->values[0]);
|
||||
}
|
||||
|
||||
void LoadMeter_display(Object* cast, RichString* out) {
|
||||
static void LoadMeter_display(Object* cast, RichString* out) {
|
||||
Meter* this = (Meter*)cast;
|
||||
char buffer[20];
|
||||
RichString_init(out);
|
||||
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
|
||||
RichString_append(out, CRT_colors[LOAD], buffer);
|
||||
RichString_write(out, CRT_colors[LOAD], buffer);
|
||||
}
|
||||
|
||||
MeterClass LoadAverageMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = LoadAverageMeter_display,
|
||||
},
|
||||
.setValues = LoadAverageMeter_setValues,
|
||||
.defaultMode = TEXT_METERMODE,
|
||||
.maxItems = 3,
|
||||
.total = 100.0,
|
||||
.attributes = LoadAverageMeter_attributes,
|
||||
.name = "LoadAverage",
|
||||
.uiName = "Load average",
|
||||
.caption = "Load average: "
|
||||
};
|
||||
|
||||
MeterClass LoadMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = LoadMeter_display,
|
||||
},
|
||||
.setValues = LoadMeter_setValues,
|
||||
.defaultMode = TEXT_METERMODE,
|
||||
.total = 100.0,
|
||||
.attributes = LoadMeter_attributes,
|
||||
.name = "Load",
|
||||
.uiName = "Load",
|
||||
.caption = "Load: "
|
||||
};
|
||||
|
@ -3,32 +3,20 @@
|
||||
#ifndef HEADER_LoadAverageMeter
|
||||
#define HEADER_LoadAverageMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - LoadAverageMeter.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"
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern int LoadAverageMeter_attributes[];
|
||||
|
||||
extern MeterType LoadAverageMeter;
|
||||
|
||||
extern int LoadMeter_attributes[];
|
||||
|
||||
extern MeterType LoadMeter;
|
||||
extern MeterClass LoadAverageMeter_class;
|
||||
|
||||
void LoadAverageMeter_setValues(Meter* this, char* buffer, int size);
|
||||
|
||||
void LoadAverageMeter_display(Object* cast, RichString* out);
|
||||
|
||||
void LoadMeter_setValues(Meter* this, char* buffer, int size);
|
||||
|
||||
void LoadMeter_display(Object* cast, RichString* out);
|
||||
extern MeterClass LoadMeter_class;
|
||||
|
||||
#endif
|
||||
|
43
Makefile.am
43
Makefile.am
@ -1,4 +1,6 @@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
bin_PROGRAMS = htop
|
||||
dist_man_MANS = htop.1
|
||||
EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py \
|
||||
@ -8,45 +10,40 @@ applications_DATA = htop.desktop
|
||||
pixmapdir = $(datadir)/pixmaps
|
||||
pixmap_DATA = htop.png
|
||||
|
||||
AM_CFLAGS = -pedantic -Wall -std=c99
|
||||
AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
htop_CFLAGS = -pedantic -Wall -Wextra -std=c99 -rdynamic -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
AM_CPPFLAGS = -DNDEBUG
|
||||
|
||||
myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \
|
||||
ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c DebugMemory.c \
|
||||
ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.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 \
|
||||
Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
|
||||
SignalItem.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
|
||||
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c
|
||||
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
|
||||
IOPriorityPanel.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.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 \
|
||||
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
|
||||
CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \
|
||||
IOPriorityPanel.h CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \
|
||||
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
|
||||
Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
|
||||
ScreenManager.h Settings.h SignalItem.h SignalsPanel.h String.h \
|
||||
SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
|
||||
Process.h
|
||||
BatteryMeter.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 \
|
||||
TraceScreen.h UptimeMeter.h UsersTable.h Vector.h Process.h AffinityPanel.h \
|
||||
HostnameMeter.h OpenFilesScreen.h Affinity.h IOPriority.h IncSet.h
|
||||
|
||||
SUFFIXES = .h
|
||||
|
||||
BUILT_SOURCES = $(myhtopheaders)
|
||||
htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h debug.h
|
||||
htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="-pg -O2"
|
||||
$(MAKE) all CFLAGS="-pg" AM_CPPFLAGS="-pg -O2 -DNDEBUG"
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="-ggdb -DDEBUG"
|
||||
|
||||
hardened-debug:
|
||||
$(MAKE) all CFLAGS="-ggdb -DDEBUG" LDFLAGS="-nopie"
|
||||
|
||||
debuglite:
|
||||
$(MAKE) all CFLAGS="-ggdb -DDEBUGLITE"
|
||||
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DDEBUG"
|
||||
|
||||
.c.h:
|
||||
scripts/MakeHeader.py $<
|
||||
|
||||
|
||||
@srcdir@/scripts/MakeHeader.py $<
|
||||
|
||||
cppcheck:
|
||||
cppcheck -q -v . --enable=all -DHAVE_CGROUP -DHAVE_OPENVZ -DHAVE_TASKSTATS
|
||||
|
@ -1,41 +1,30 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - MemoryMeter.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 "MemoryMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "CRT.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>
|
||||
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
int MemoryMeter_attributes[] = {
|
||||
MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE
|
||||
};
|
||||
|
||||
MeterType MemoryMeter = {
|
||||
.setValues = MemoryMeter_setValues,
|
||||
.display = MemoryMeter_display,
|
||||
.mode = BAR_METERMODE,
|
||||
.items = 3,
|
||||
.total = 100.0,
|
||||
.attributes = MemoryMeter_attributes,
|
||||
"Memory",
|
||||
"Memory",
|
||||
"Mem"
|
||||
};
|
||||
|
||||
void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
static void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
long int usedMem = this->pl->usedMem;
|
||||
long int buffersMem = this->pl->buffersMem;
|
||||
long int cachedMem = this->pl->cachedMem;
|
||||
@ -47,16 +36,15 @@ void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
|
||||
snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024);
|
||||
}
|
||||
|
||||
void MemoryMeter_display(Object* cast, RichString* out) {
|
||||
static void MemoryMeter_display(Object* cast, RichString* out) {
|
||||
char buffer[50];
|
||||
Meter* this = (Meter*)cast;
|
||||
int div = 1024; char* format = "%ldM ";
|
||||
long int totalMem = this->total / div;
|
||||
long int usedMem = this->values[0] / div;
|
||||
long int buffersMem = this->values[1] / div;
|
||||
long int cachedMem = this->values[2] / div;
|
||||
RichString_init(out);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], ":");
|
||||
int k = 1024; const char* format = "%ldM ";
|
||||
long int totalMem = this->total / k;
|
||||
long int usedMem = this->values[0] / k;
|
||||
long int buffersMem = this->values[1] / k;
|
||||
long int cachedMem = this->values[2] / k;
|
||||
RichString_write(out, CRT_colors[METER_TEXT], ":");
|
||||
sprintf(buffer, format, totalMem);
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
sprintf(buffer, format, usedMem);
|
||||
@ -64,8 +52,24 @@ void MemoryMeter_display(Object* cast, RichString* out) {
|
||||
RichString_append(out, CRT_colors[MEMORY_USED], buffer);
|
||||
sprintf(buffer, format, buffersMem);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "buffers:");
|
||||
RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer);
|
||||
RichString_append(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer);
|
||||
sprintf(buffer, format, cachedMem);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "cache:");
|
||||
RichString_append(out, CRT_colors[MEMORY_CACHE], buffer);
|
||||
}
|
||||
|
||||
MeterClass MemoryMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = MemoryMeter_display,
|
||||
},
|
||||
.setValues = MemoryMeter_setValues,
|
||||
.defaultMode = BAR_METERMODE,
|
||||
.maxItems = 3,
|
||||
.total = 100.0,
|
||||
.attributes = MemoryMeter_attributes,
|
||||
"Memory",
|
||||
"Memory",
|
||||
"Mem"
|
||||
};
|
||||
|
@ -3,31 +3,16 @@
|
||||
#ifndef HEADER_MemoryMeter
|
||||
#define HEADER_MemoryMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - MemoryMeter.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"
|
||||
|
||||
#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 MeterType MemoryMeter;
|
||||
|
||||
void MemoryMeter_setValues(Meter* this, char* buffer, int size);
|
||||
|
||||
void MemoryMeter_display(Object* cast, RichString* out);
|
||||
extern MeterClass MemoryMeter_class;
|
||||
|
||||
#endif
|
||||
|
504
Meter.c
504
Meter.c
@ -1,93 +1,11 @@
|
||||
/*
|
||||
htop - Meter.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
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 "Object.h"
|
||||
#include "CRT.h"
|
||||
#include "ListItem.h"
|
||||
#include "String.h"
|
||||
#include "ProcessList.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 "MemoryMeter.h"
|
||||
@ -95,7 +13,105 @@ typedef enum {
|
||||
#include "TasksMeter.h"
|
||||
#include "LoadAverageMeter.h"
|
||||
#include "UptimeMeter.h"
|
||||
#include "BatteryMeter.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
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@ -104,110 +120,77 @@ typedef enum {
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
char* METER_CLASS = "Meter";
|
||||
#else
|
||||
#define METER_CLASS NULL
|
||||
#endif
|
||||
MeterClass Meter_class = {
|
||||
.super = {
|
||||
.extends = Class(Object)
|
||||
}
|
||||
};
|
||||
|
||||
MeterType* Meter_types[] = {
|
||||
&CPUMeter,
|
||||
&ClockMeter,
|
||||
&LoadAverageMeter,
|
||||
&LoadMeter,
|
||||
&MemoryMeter,
|
||||
&SwapMeter,
|
||||
&TasksMeter,
|
||||
&UptimeMeter,
|
||||
&AllCPUsMeter,
|
||||
MeterClass* Meter_types[] = {
|
||||
&CPUMeter_class,
|
||||
&ClockMeter_class,
|
||||
&LoadAverageMeter_class,
|
||||
&LoadMeter_class,
|
||||
&MemoryMeter_class,
|
||||
&SwapMeter_class,
|
||||
&TasksMeter_class,
|
||||
&UptimeMeter_class,
|
||||
&BatteryMeter_class,
|
||||
&HostnameMeter_class,
|
||||
&AllCPUsMeter_class,
|
||||
&AllCPUs2Meter_class,
|
||||
&LeftCPUsMeter_class,
|
||||
&RightCPUsMeter_class,
|
||||
&LeftCPUs2Meter_class,
|
||||
&RightCPUs2Meter_class,
|
||||
&BlankMeter_class,
|
||||
NULL
|
||||
};
|
||||
|
||||
static MeterMode BarMeterMode = {
|
||||
.uiName = "Bar",
|
||||
.h = 1,
|
||||
.draw = BarMeterMode_draw,
|
||||
};
|
||||
|
||||
static MeterMode TextMeterMode = {
|
||||
.uiName = "Text",
|
||||
.h = 1,
|
||||
.draw = TextMeterMode_draw,
|
||||
};
|
||||
|
||||
#ifdef USE_FUNKY_MODES
|
||||
|
||||
static MeterMode GraphMeterMode = {
|
||||
.uiName = "Graph",
|
||||
.h = 3,
|
||||
.draw = GraphMeterMode_draw,
|
||||
};
|
||||
|
||||
static MeterMode LEDMeterMode = {
|
||||
.uiName = "LED",
|
||||
.h = 3,
|
||||
.draw = LEDMeterMode_draw,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
MeterMode* Meter_modes[] = {
|
||||
NULL,
|
||||
&BarMeterMode,
|
||||
&TextMeterMode,
|
||||
#ifdef USE_FUNKY_MODES
|
||||
&GraphMeterMode,
|
||||
&LEDMeterMode,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static RichString Meter_stringBuffer;
|
||||
|
||||
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;
|
||||
Meter* Meter_new(ProcessList* pl, int param, MeterClass* type) {
|
||||
Meter* this = calloc(1, sizeof(Meter));
|
||||
Object_setClass(this, type);
|
||||
this->h = 1;
|
||||
this->type = type;
|
||||
this->param = param;
|
||||
this->pl = pl;
|
||||
this->values = calloc(sizeof(double), type->items);
|
||||
char maxItems = type->maxItems;
|
||||
if (maxItems == 0) {
|
||||
maxItems = 1;
|
||||
}
|
||||
type->curItems = maxItems;
|
||||
this->values = calloc(maxItems, sizeof(double));
|
||||
this->total = type->total;
|
||||
this->caption = strdup(type->caption);
|
||||
Meter_setMode(this, type->mode);
|
||||
if (this->type->init)
|
||||
this->type->init(this);
|
||||
if (Meter_initFn(this))
|
||||
Meter_init(this);
|
||||
Meter_setMode(this, type->defaultMode);
|
||||
return this;
|
||||
}
|
||||
|
||||
void Meter_delete(Object* cast) {
|
||||
if (!cast)
|
||||
return;
|
||||
Meter* this = (Meter*) cast;
|
||||
assert (this != NULL);
|
||||
if (this->type->done) {
|
||||
this->type->done(this);
|
||||
if (Meter_doneFn(this)) {
|
||||
Meter_done(this);
|
||||
}
|
||||
if (this->drawBuffer)
|
||||
free(this->drawBuffer);
|
||||
if (this->drawData)
|
||||
free(this->drawData);
|
||||
free(this->caption);
|
||||
free(this->values);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void Meter_setCaption(Meter* this, char* caption) {
|
||||
void Meter_setCaption(Meter* this, const char* caption) {
|
||||
free(this->caption);
|
||||
this->caption = strdup(caption);
|
||||
}
|
||||
|
||||
static inline void Meter_displayToStringBuffer(Meter* this, char* buffer) {
|
||||
MeterType* type = this->type;
|
||||
Object_Display display = ((Object*)this)->display;
|
||||
if (display) {
|
||||
display((Object*)this, &Meter_stringBuffer);
|
||||
static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) {
|
||||
if (Object_displayFn(this)) {
|
||||
Object_display(this, out);
|
||||
} else {
|
||||
RichString_initVal(Meter_stringBuffer);
|
||||
RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer);
|
||||
RichString_write(out, CRT_colors[Meter_attributes(this)[0]], buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,15 +200,15 @@ void Meter_setMode(Meter* this, int modeIndex) {
|
||||
if (!modeIndex)
|
||||
modeIndex = 1;
|
||||
assert(modeIndex < LAST_METERMODE);
|
||||
if (this->type->mode == 0) {
|
||||
this->draw = this->type->draw;
|
||||
if (this->type->setMode)
|
||||
this->type->setMode(this, modeIndex);
|
||||
if (Meter_defaultMode(this) == CUSTOM_METERMODE) {
|
||||
this->draw = Meter_drawFn(this);
|
||||
if (Meter_updateModeFn(this))
|
||||
Meter_updateMode(this, modeIndex);
|
||||
} else {
|
||||
assert(modeIndex >= 1);
|
||||
if (this->drawBuffer)
|
||||
free(this->drawBuffer);
|
||||
this->drawBuffer = NULL;
|
||||
if (this->drawData)
|
||||
free(this->drawData);
|
||||
this->drawData = NULL;
|
||||
|
||||
MeterMode* mode = Meter_modes[modeIndex];
|
||||
this->draw = mode->draw;
|
||||
@ -235,7 +218,6 @@ void Meter_setMode(Meter* this, int modeIndex) {
|
||||
}
|
||||
|
||||
ListItem* Meter_toListItem(Meter* this) {
|
||||
MeterType* type = this->type;
|
||||
char mode[21];
|
||||
if (this->mode)
|
||||
snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName);
|
||||
@ -247,41 +229,41 @@ ListItem* Meter_toListItem(Meter* this) {
|
||||
else
|
||||
number[0] = '\0';
|
||||
char buffer[51];
|
||||
snprintf(buffer, 50, "%s%s%s", type->uiName, number, mode);
|
||||
snprintf(buffer, 50, "%s%s%s", Meter_uiName(this), number, mode);
|
||||
return ListItem_new(buffer, 0);
|
||||
}
|
||||
|
||||
/* ---------- TextMeterMode ---------- */
|
||||
|
||||
void TextMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
MeterType* type = this->type;
|
||||
static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
char buffer[METER_BUFFER_LEN];
|
||||
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
(void) w;
|
||||
|
||||
attrset(CRT_colors[METER_TEXT]);
|
||||
mvaddstr(y, x, this->caption);
|
||||
int captionLen = strlen(this->caption);
|
||||
w -= captionLen;
|
||||
x += captionLen;
|
||||
Meter_displayToStringBuffer(this, buffer);
|
||||
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
mvaddchstr(y, x, Meter_stringBuffer.chstr);
|
||||
RichString_begin(out);
|
||||
Meter_displayBuffer(this, buffer, &out);
|
||||
RichString_printVal(out, y, x);
|
||||
RichString_end(out);
|
||||
}
|
||||
|
||||
/* ---------- BarMeterMode ---------- */
|
||||
|
||||
static char BarMeterMode_characters[] = "|#*@$%&";
|
||||
|
||||
void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
MeterType* type = this->type;
|
||||
static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
char buffer[METER_BUFFER_LEN];
|
||||
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
|
||||
w -= 2;
|
||||
attrset(CRT_colors[METER_TEXT]);
|
||||
mvaddstr(y, x, this->caption);
|
||||
int captionLen = strlen(this->caption);
|
||||
int captionLen = 3;
|
||||
mvaddnstr(y, x, this->caption, captionLen);
|
||||
x += captionLen;
|
||||
w -= captionLen;
|
||||
attrset(CRT_colors[BAR_BORDER]);
|
||||
@ -290,18 +272,24 @@ void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
|
||||
w--;
|
||||
x++;
|
||||
char bar[w];
|
||||
|
||||
if (w < 1) {
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
return;
|
||||
}
|
||||
char bar[w + 1];
|
||||
|
||||
int blockSizes[10];
|
||||
for (int i = 0; i < w; i++)
|
||||
bar[i] = ' ';
|
||||
|
||||
sprintf(bar + (w-strlen(buffer)), "%s", buffer);
|
||||
const size_t barOffset = w - MIN((int)strlen(buffer), w);
|
||||
snprintf(bar + barOffset, w - barOffset + 1, "%s", buffer);
|
||||
|
||||
// First draw in the bar[] buffer...
|
||||
double total = 0.0;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < type->items; i++) {
|
||||
int items = Meter_getItems(this);
|
||||
for (int i = 0; i < items; i++) {
|
||||
double value = this->values[i];
|
||||
value = MAX(value, 0);
|
||||
value = MIN(value, this->total);
|
||||
@ -322,13 +310,12 @@ void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
}
|
||||
}
|
||||
offset = nextOffset;
|
||||
total += this->values[i];
|
||||
}
|
||||
|
||||
// ...then print the buffer.
|
||||
offset = 0;
|
||||
for (int i = 0; i < type->items; i++) {
|
||||
attrset(CRT_colors[type->attributes[i]]);
|
||||
for (int i = 0; i < items; i++) {
|
||||
attrset(CRT_colors[Meter_attributes(this)[i]]);
|
||||
mvaddnstr(y, x + offset, bar + offset, blockSizes[i]);
|
||||
offset += blockSizes[i];
|
||||
offset = MAX(offset, 0);
|
||||
@ -343,8 +330,6 @@ void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
}
|
||||
|
||||
#ifdef USE_FUNKY_MODES
|
||||
|
||||
/* ---------- GraphMeterMode ---------- */
|
||||
|
||||
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
|
||||
@ -359,35 +344,44 @@ static int GraphMeterMode_colors[21] = {
|
||||
GRAPH_8, GRAPH_8, GRAPH_9
|
||||
};
|
||||
|
||||
static char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_";
|
||||
static const char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_";
|
||||
|
||||
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->drawBuffer) this->drawBuffer = calloc(sizeof(double), METER_BUFFER_LEN);
|
||||
double* drawBuffer = (double*) this->drawBuffer;
|
||||
if (!this->drawData) this->drawData = calloc(1, sizeof(GraphData));
|
||||
GraphData* data = (GraphData*) this->drawData;
|
||||
const int nValues = METER_BUFFER_LEN;
|
||||
|
||||
for (int i = 0; i < METER_BUFFER_LEN - 1; i++)
|
||||
drawBuffer[i] = drawBuffer[i+1];
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
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));
|
||||
|
||||
MeterType* type = this->type;
|
||||
char buffer[METER_BUFFER_LEN];
|
||||
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
for (int i = 0; i < nValues - 1; i++)
|
||||
data->values[i] = data->values[i+1];
|
||||
|
||||
char buffer[nValues];
|
||||
Meter_setValues(this, buffer, nValues - 1);
|
||||
|
||||
double value = 0.0;
|
||||
for (int i = 0; i < type->items; i++)
|
||||
int items = Meter_getItems(this);
|
||||
for (int i = 0; i < items; i++)
|
||||
value += this->values[i];
|
||||
value /= this->total;
|
||||
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];
|
||||
data->values[nValues - 1] = value;
|
||||
}
|
||||
|
||||
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+1, ' ' );
|
||||
DrawDot( CRT_colors[DEFAULT_COLOR], y+2, ' ' );
|
||||
|
||||
double threshold = 1.00;
|
||||
for (int i = 0; i < 21; i++, threshold -= 0.05)
|
||||
for (int j = 0; j < 21; j++, threshold -= 0.05)
|
||||
if (value >= threshold) {
|
||||
DrawDot(CRT_colors[GraphMeterMode_colors[i]], y+(i/7.0), GraphMeterMode_characters[i]);
|
||||
DrawDot(CRT_colors[GraphMeterMode_colors[j]], y+(j/7.0), GraphMeterMode_characters[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -396,38 +390,114 @@ void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
|
||||
/* ---------- LEDMeterMode ---------- */
|
||||
|
||||
static char* LEDMeterMode_digits[3][10] = {
|
||||
static const char* LEDMeterMode_digitsAscii[3][10] = {
|
||||
{ " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "},
|
||||
{ "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"},
|
||||
{ "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"},
|
||||
};
|
||||
|
||||
static const char* LEDMeterMode_digitsUtf8[3][10] = {
|
||||
{ "┌──┐"," ┐ ","╶──┐","╶──┐","╷ ╷","┌──╴","┌──╴","╶──┐","┌──┐","┌──┐"},
|
||||
{ "│ │"," │ ","┌──┘"," ──┤","└──┤","└──┐","├──┐"," │","├──┤","└──┤"},
|
||||
{ "└──┘"," ╵ ","└──╴","╶──┘"," ╵","╶──┘","└──┘"," ╵","└──┘"," ──┘"},
|
||||
};
|
||||
|
||||
static void LEDMeterMode_drawDigit(int x, int y, int n) {
|
||||
if (CRT_utf8) {
|
||||
for (int i = 0; i < 3; i++)
|
||||
mvaddstr(y+i, x, LEDMeterMode_digits[i][n]);
|
||||
mvaddstr(y+i, x, LEDMeterMode_digitsUtf8[i][n]);
|
||||
} else {
|
||||
for (int i = 0; i < 3; i++)
|
||||
mvaddstr(y+i, x, LEDMeterMode_digitsAscii[i][n]);
|
||||
}
|
||||
}
|
||||
|
||||
void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
MeterType* type = this->type;
|
||||
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
(void) w;
|
||||
char buffer[METER_BUFFER_LEN];
|
||||
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
||||
|
||||
Meter_displayToStringBuffer(this, buffer);
|
||||
RichString_begin(out);
|
||||
Meter_displayBuffer(this, buffer, &out);
|
||||
|
||||
int yText = CRT_utf8 ? y+1 : y+2;
|
||||
attrset(CRT_colors[LED_COLOR]);
|
||||
mvaddstr(y+2, x, this->caption);
|
||||
mvaddstr(yText, x, this->caption);
|
||||
int xx = x + strlen(this->caption);
|
||||
for (int i = 0; i < Meter_stringBuffer.len; i++) {
|
||||
char c = Meter_stringBuffer.chstr[i];
|
||||
int len = RichString_sizeVal(out);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = RichString_getCharVal(out, i);
|
||||
if (c >= '0' && c <= '9') {
|
||||
LEDMeterMode_drawDigit(xx, y, c-48);
|
||||
xx += 4;
|
||||
} else {
|
||||
mvaddch(y+2, xx, c);
|
||||
mvaddch(yText, xx, c);
|
||||
xx += 1;
|
||||
}
|
||||
}
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(out);
|
||||
}
|
||||
|
||||
#endif
|
||||
static MeterMode BarMeterMode = {
|
||||
.uiName = "Bar",
|
||||
.h = 1,
|
||||
.draw = BarMeterMode_draw,
|
||||
};
|
||||
|
||||
static MeterMode TextMeterMode = {
|
||||
.uiName = "Text",
|
||||
.h = 1,
|
||||
.draw = TextMeterMode_draw,
|
||||
};
|
||||
|
||||
static MeterMode GraphMeterMode = {
|
||||
.uiName = "Graph",
|
||||
.h = 3,
|
||||
.draw = GraphMeterMode_draw,
|
||||
};
|
||||
|
||||
static MeterMode LEDMeterMode = {
|
||||
.uiName = "LED",
|
||||
.h = 3,
|
||||
.draw = LEDMeterMode_draw,
|
||||
};
|
||||
|
||||
MeterMode* Meter_modes[] = {
|
||||
NULL,
|
||||
&BarMeterMode,
|
||||
&TextMeterMode,
|
||||
&GraphMeterMode,
|
||||
&LEDMeterMode,
|
||||
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 = ""
|
||||
};
|
||||
|
144
Meter.h
144
Meter.h
@ -4,99 +4,91 @@
|
||||
#define HEADER_Meter
|
||||
/*
|
||||
htop - Meter.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
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 "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef USE_FUNKY_MODES
|
||||
#define USE_FUNKY_MODES 1
|
||||
#endif
|
||||
|
||||
#define METER_BUFFER_LEN 128
|
||||
|
||||
#include "ListItem.h"
|
||||
#include "ProcessList.h"
|
||||
|
||||
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_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);
|
||||
|
||||
struct MeterMode_ {
|
||||
Meter_Draw draw;
|
||||
char* uiName;
|
||||
int h;
|
||||
};
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
||||
#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;
|
||||
MeterType* type;
|
||||
int mode;
|
||||
int param;
|
||||
Meter_Draw draw;
|
||||
void* drawBuffer;
|
||||
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,
|
||||
#ifdef USE_FUNKY_MODES
|
||||
GRAPH_METERMODE,
|
||||
LED_METERMODE,
|
||||
#endif
|
||||
LAST_METERMODE
|
||||
} 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
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@ -105,25 +97,15 @@ typedef enum {
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* METER_CLASS;
|
||||
#else
|
||||
#define METER_CLASS NULL
|
||||
#endif
|
||||
extern MeterClass Meter_class;
|
||||
|
||||
extern MeterType* Meter_types[];
|
||||
extern MeterClass* Meter_types[];
|
||||
|
||||
#ifdef USE_FUNKY_MODES
|
||||
|
||||
#endif
|
||||
|
||||
extern MeterMode* Meter_modes[];
|
||||
|
||||
Meter* Meter_new(ProcessList* pl, int param, MeterType* type);
|
||||
Meter* Meter_new(ProcessList* pl, int param, MeterClass* type);
|
||||
|
||||
void Meter_delete(Object* cast);
|
||||
|
||||
void Meter_setCaption(Meter* this, char* caption);
|
||||
void Meter_setCaption(Meter* this, const char* caption);
|
||||
|
||||
void Meter_setMode(Meter* this, int modeIndex);
|
||||
|
||||
@ -131,24 +113,20 @@ ListItem* Meter_toListItem(Meter* this);
|
||||
|
||||
/* ---------- TextMeterMode ---------- */
|
||||
|
||||
void TextMeterMode_draw(Meter* this, int x, int y, int w);
|
||||
|
||||
/* ---------- BarMeterMode ---------- */
|
||||
|
||||
void BarMeterMode_draw(Meter* this, int x, int y, int w);
|
||||
|
||||
#ifdef USE_FUNKY_MODES
|
||||
|
||||
/* ---------- GraphMeterMode ---------- */
|
||||
|
||||
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
|
||||
|
||||
void GraphMeterMode_draw(Meter* this, int x, int y, int w);
|
||||
|
||||
/* ---------- LEDMeterMode ---------- */
|
||||
|
||||
void LEDMeterMode_draw(Meter* this, int x, int y, int w);
|
||||
|
||||
#endif
|
||||
extern MeterMode* Meter_modes[];
|
||||
|
||||
/* Blank meter */
|
||||
|
||||
extern int BlankMeter_attributes[];
|
||||
|
||||
extern MeterClass BlankMeter_class;
|
||||
|
||||
#endif
|
||||
|
@ -1,14 +1,19 @@
|
||||
/*
|
||||
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 "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*{
|
||||
#include "Panel.h"
|
||||
#include "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
typedef struct MetersPanel_ {
|
||||
Panel super;
|
||||
@ -20,32 +25,14 @@ typedef struct MetersPanel_ {
|
||||
|
||||
}*/
|
||||
|
||||
MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr) {
|
||||
MetersPanel* this = (MetersPanel*) malloc(sizeof(MetersPanel));
|
||||
Panel* super = (Panel*) this;
|
||||
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
|
||||
((Object*)this)->delete = MetersPanel_delete;
|
||||
|
||||
this->settings = settings;
|
||||
this->meters = meters;
|
||||
this->scr = scr;
|
||||
super->eventHandler = MetersPanel_EventHandler;
|
||||
Panel_setHeader(super, header);
|
||||
for (int i = 0; i < Vector_size(meters); i++) {
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
Panel_add(super, (Object*) Meter_toListItem(meter));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void MetersPanel_delete(Object* object) {
|
||||
static void MetersPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
MetersPanel* this = (MetersPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
|
||||
static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
|
||||
MetersPanel* this = (MetersPanel*) super;
|
||||
|
||||
int selected = Panel_getSelectedIndex(super);
|
||||
@ -97,9 +84,34 @@ HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
|
||||
}
|
||||
if (result == HANDLED) {
|
||||
Header* header = this->settings->header;
|
||||
this->settings->changed = true;
|
||||
Header_calculateHeight(header);
|
||||
Header_draw(header);
|
||||
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PanelClass MetersPanel_class = {
|
||||
.super = {
|
||||
.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_init(super, 1, 1, 1, 1, Class(ListItem), true);
|
||||
|
||||
this->settings = settings;
|
||||
this->meters = meters;
|
||||
this->scr = scr;
|
||||
Panel_setHeader(super, header);
|
||||
for (int i = 0; i < Vector_size(meters); i++) {
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
Panel_add(super, (Object*) Meter_toListItem(meter));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -2,16 +2,17 @@
|
||||
|
||||
#ifndef 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 "Settings.h"
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
typedef struct MetersPanel_ {
|
||||
Panel super;
|
||||
|
||||
@ -21,10 +22,8 @@ typedef struct MetersPanel_ {
|
||||
} MetersPanel;
|
||||
|
||||
|
||||
MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr);
|
||||
extern PanelClass MetersPanel_class;
|
||||
|
||||
void MetersPanel_delete(Object* object);
|
||||
|
||||
HandlerResult MetersPanel_EventHandler(Panel* super, int ch);
|
||||
MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr);
|
||||
|
||||
#endif
|
||||
|
4
NEWS
4
NEWS
@ -1,5 +1,5 @@
|
||||
|
||||
See the ChangeLog for news of the past.
|
||||
See the TODO list for news of the future.
|
||||
See the commit history for news of the past.
|
||||
See the bug tracker for news of the future.
|
||||
Run the program for news of the present.
|
||||
|
||||
|
67
Object.c
67
Object.c
@ -1,24 +1,14 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Object.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 "Object.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
|
||||
#include "RichString.h"
|
||||
|
||||
typedef struct Object_ Object;
|
||||
|
||||
@ -26,32 +16,47 @@ typedef void(*Object_Display)(Object*, RichString*);
|
||||
typedef int(*Object_Compare)(const void*, const void*);
|
||||
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_ {
|
||||
#ifdef DEBUG
|
||||
char* class;
|
||||
#endif
|
||||
Object_Display display;
|
||||
Object_Delete delete;
|
||||
ObjectClass* klass;
|
||||
};
|
||||
|
||||
}*/
|
||||
|
||||
#ifdef DEBUG
|
||||
char* OBJECT_CLASS = "Object";
|
||||
|
||||
#else
|
||||
#define OBJECT_CLASS NULL
|
||||
#endif
|
||||
ObjectClass Object_class = {
|
||||
.extends = NULL
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void Object_setClass(void* this, char* class) {
|
||||
((Object*)this)->class = class;
|
||||
bool Object_isA(Object* o, const ObjectClass* klass) {
|
||||
if (!o)
|
||||
return false;
|
||||
const ObjectClass* type = o->klass;
|
||||
while (type) {
|
||||
if (type == klass)
|
||||
return true;
|
||||
type = type->extends;
|
||||
}
|
||||
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
50
Object.h
50
Object.h
@ -3,24 +3,13 @@
|
||||
#ifndef HEADER_Object
|
||||
#define HEADER_Object
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Object.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 "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;
|
||||
|
||||
@ -28,26 +17,35 @@ typedef void(*Object_Display)(Object*, RichString*);
|
||||
typedef int(*Object_Compare)(const void*, const void*);
|
||||
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_ {
|
||||
#ifdef DEBUG
|
||||
char* class;
|
||||
#endif
|
||||
Object_Display display;
|
||||
Object_Delete delete;
|
||||
ObjectClass* klass;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* OBJECT_CLASS;
|
||||
|
||||
#else
|
||||
#define OBJECT_CLASS NULL
|
||||
#endif
|
||||
extern ObjectClass Object_class;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void Object_setClass(void* this, char* class);
|
||||
|
||||
void Object_display(Object* this, RichString* out);
|
||||
bool Object_isA(Object* o, const ObjectClass* klass);
|
||||
|
||||
#endif
|
||||
|
||||
|
246
OpenFilesScreen.c
Normal file
246
OpenFilesScreen.c
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
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);
|
||||
}
|
45
OpenFilesScreen.h
Normal file
45
OpenFilesScreen.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* 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
|
272
Panel.c
272
Panel.c
@ -1,27 +1,29 @@
|
||||
/*
|
||||
htop - Panel.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Object.h"
|
||||
#include "Panel.h"
|
||||
#include "Vector.h"
|
||||
|
||||
#include "CRT.h"
|
||||
#include "RichString.h"
|
||||
#include "ListItem.h"
|
||||
#include "String.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <curses.h>
|
||||
//#link curses
|
||||
|
||||
/*{
|
||||
#include "Object.h"
|
||||
#include "Vector.h"
|
||||
|
||||
typedef struct Panel_ Panel;
|
||||
|
||||
@ -31,20 +33,32 @@ typedef enum HandlerResult_ {
|
||||
BREAK_LOOP
|
||||
} HandlerResult;
|
||||
|
||||
#define EVENT_SETSELECTED -1
|
||||
|
||||
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_ {
|
||||
Object super;
|
||||
PanelClass* class;
|
||||
int x, y, w, h;
|
||||
WINDOW* window;
|
||||
Vector* items;
|
||||
int selected;
|
||||
int scrollV, scrollH;
|
||||
int scrollHAmount;
|
||||
int oldSelected;
|
||||
char* eventHandlerBuffer;
|
||||
int scrollV;
|
||||
short scrollH;
|
||||
bool needsRedraw;
|
||||
RichString header;
|
||||
Panel_EventHandler eventHandler;
|
||||
};
|
||||
|
||||
}*/
|
||||
@ -56,18 +70,24 @@ struct Panel_ {
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
char* PANEL_CLASS = "Panel";
|
||||
#else
|
||||
#define PANEL_CLASS NULL
|
||||
#endif
|
||||
#define KEY_CTRLN 0016 /* control-n key */
|
||||
#define KEY_CTRLP 0020 /* control-p key */
|
||||
#define KEY_CTRLF 0006 /* control-f key */
|
||||
#define KEY_CTRLB 0002 /* control-b key */
|
||||
|
||||
PanelClass Panel_class = {
|
||||
.super = {
|
||||
.extends = Class(Object),
|
||||
.delete = Panel_delete
|
||||
},
|
||||
.eventHandler = Panel_selectByTyping
|
||||
};
|
||||
|
||||
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
|
||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type) {
|
||||
Panel* this;
|
||||
this = malloc(sizeof(Panel));
|
||||
Object_setClass(this, Class(Panel));
|
||||
Panel_init(this, x, y, w, h, type, owner);
|
||||
this->items->compare = compare;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -77,46 +97,38 @@ void Panel_delete(Object* cast) {
|
||||
free(this);
|
||||
}
|
||||
|
||||
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;
|
||||
void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool owner) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->eventHandler = NULL;
|
||||
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
|
||||
this->eventHandlerBuffer = NULL;
|
||||
this->items = Vector_new(type, owner, DEFAULT_SIZE);
|
||||
this->scrollV = 0;
|
||||
this->scrollH = 0;
|
||||
this->selected = 0;
|
||||
this->oldSelected = 0;
|
||||
this->needsRedraw = true;
|
||||
this->header.len = 0;
|
||||
if (String_eq(CRT_termType, "linux"))
|
||||
this->scrollHAmount = 40;
|
||||
else
|
||||
this->scrollHAmount = 5;
|
||||
RichString_beginAllocated(this->header);
|
||||
}
|
||||
|
||||
void Panel_done(Panel* this) {
|
||||
assert (this != NULL);
|
||||
free(this->eventHandlerBuffer);
|
||||
Vector_delete(this->items);
|
||||
RichString_end(this->header);
|
||||
}
|
||||
|
||||
inline void Panel_setRichHeader(Panel* this, RichString header) {
|
||||
RichString* Panel_getHeader(Panel* this) {
|
||||
assert (this != NULL);
|
||||
|
||||
this->header = header;
|
||||
this->needsRedraw = true;
|
||||
return &(this->header);
|
||||
}
|
||||
|
||||
inline void Panel_setHeader(Panel* this, char* header) {
|
||||
Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
|
||||
}
|
||||
|
||||
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
|
||||
this->eventHandler = eh;
|
||||
inline void Panel_setHeader(Panel* this, const char* header) {
|
||||
RichString_write(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
|
||||
void Panel_move(Panel* this, int x, int y) {
|
||||
@ -130,7 +142,7 @@ void Panel_move(Panel* this, int x, int y) {
|
||||
void Panel_resize(Panel* this, int w, int h) {
|
||||
assert (this != NULL);
|
||||
|
||||
if (this->header.len > 0)
|
||||
if (RichString_sizeVal(this->header) > 0)
|
||||
h--;
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
@ -185,8 +197,10 @@ Object* Panel_remove(Panel* this, int i) {
|
||||
|
||||
Object* Panel_getSelected(Panel* this) {
|
||||
assert (this != NULL);
|
||||
|
||||
if (Vector_size(this->items) > 0)
|
||||
return Vector_get(this->items, this->selected);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Panel_moveSelectedUp(Panel* this) {
|
||||
@ -211,7 +225,7 @@ int Panel_getSelectedIndex(Panel* this) {
|
||||
return this->selected;
|
||||
}
|
||||
|
||||
int Panel_getSize(Panel* this) {
|
||||
int Panel_size(Panel* this) {
|
||||
assert (this != NULL);
|
||||
|
||||
return Vector_size(this->items);
|
||||
@ -222,23 +236,23 @@ void Panel_setSelected(Panel* this, int selected) {
|
||||
|
||||
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
|
||||
this->selected = selected;
|
||||
if (Panel_eventHandlerFn(this)) {
|
||||
Panel_eventHandler(this, EVENT_SETSELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel_draw(Panel* this, bool focus) {
|
||||
assert (this != NULL);
|
||||
|
||||
int first, last;
|
||||
int itemCount = Vector_size(this->items);
|
||||
int scrollH = this->scrollH;
|
||||
int y = this->y; int x = this->x;
|
||||
first = this->scrollV;
|
||||
|
||||
if (this->h > itemCount) {
|
||||
last = this->scrollV + itemCount;
|
||||
move(y + last, x + 0);
|
||||
} else {
|
||||
last = MIN(itemCount, this->scrollV + this->h);
|
||||
int first = this->scrollV;
|
||||
if (itemCount > this->h && first > itemCount - this->h) {
|
||||
first = itemCount - this->h;
|
||||
this->scrollV = first;
|
||||
}
|
||||
int last = MIN(itemCount, first + MIN(itemCount, this->h));
|
||||
if (this->selected < first) {
|
||||
first = this->selected;
|
||||
this->scrollV = first;
|
||||
@ -253,15 +267,16 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
assert(first >= 0);
|
||||
assert(last <= itemCount);
|
||||
|
||||
if (this->header.len > 0) {
|
||||
int headerLen = RichString_sizeVal(this->header);
|
||||
if (headerLen > 0) {
|
||||
int attr = focus
|
||||
? CRT_colors[PANEL_HEADER_FOCUS]
|
||||
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
||||
attrset(attr);
|
||||
mvhline(y, x, ' ', this->w);
|
||||
if (scrollH < this->header.len) {
|
||||
mvaddchnstr(y, x, this->header.chstr + scrollH,
|
||||
MIN(this->header.len - scrollH, this->w));
|
||||
if (scrollH < headerLen) {
|
||||
RichString_printoffnVal(this->header, y, x, scrollH,
|
||||
MIN(headerLen - scrollH, this->w));
|
||||
}
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
y++;
|
||||
@ -275,22 +290,22 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
|
||||
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
|
||||
Object* itemObj = Vector_get(this->items, i);
|
||||
RichString itemRef;
|
||||
RichString_initVal(itemRef);
|
||||
itemObj->display(itemObj, &itemRef);
|
||||
int amt = MIN(itemRef.len - scrollH, this->w);
|
||||
if (i == this->selected) {
|
||||
assert(itemObj); if(!itemObj) continue;
|
||||
RichString_begin(item);
|
||||
Object_display(itemObj, &item);
|
||||
int itemLen = RichString_sizeVal(item);
|
||||
int amt = MIN(itemLen - scrollH, this->w);
|
||||
bool selected = (i == this->selected);
|
||||
if (selected) {
|
||||
attrset(highlight);
|
||||
RichString_setAttr(&itemRef, highlight);
|
||||
mvhline(y + j, x+0, ' ', this->w);
|
||||
if (amt > 0)
|
||||
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
} else {
|
||||
mvhline(y+j, x+0, ' ', this->w);
|
||||
if (amt > 0)
|
||||
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
|
||||
RichString_setAttr(&item, highlight);
|
||||
}
|
||||
mvhline(y + j, x, ' ', this->w);
|
||||
if (amt > 0)
|
||||
RichString_printoffnVal(item, y+j, x, scrollH, amt);
|
||||
if (selected)
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(item);
|
||||
}
|
||||
for (int i = y + (last - first); i < y + this->h; i++)
|
||||
mvhline(i, x+0, ' ', this->w);
|
||||
@ -298,64 +313,139 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
|
||||
} else {
|
||||
Object* oldObj = Vector_get(this->items, this->oldSelected);
|
||||
RichString oldRef;
|
||||
RichString_initVal(oldRef);
|
||||
oldObj->display(oldObj, &oldRef);
|
||||
assert(oldObj);
|
||||
RichString_begin(old);
|
||||
Object_display(oldObj, &old);
|
||||
int oldLen = RichString_sizeVal(old);
|
||||
Object* newObj = Vector_get(this->items, this->selected);
|
||||
RichString newRef;
|
||||
RichString_initVal(newRef);
|
||||
newObj->display(newObj, &newRef);
|
||||
RichString_begin(new);
|
||||
Object_display(newObj, &new);
|
||||
int newLen = RichString_sizeVal(new);
|
||||
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
|
||||
if (scrollH < oldRef.len)
|
||||
mvaddchnstr(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + this->scrollH, MIN(oldRef.len - scrollH, this->w));
|
||||
if (scrollH < oldLen)
|
||||
RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x,
|
||||
scrollH, MIN(oldLen - scrollH, this->w));
|
||||
attrset(highlight);
|
||||
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
|
||||
RichString_setAttr(&newRef, highlight);
|
||||
if (scrollH < newRef.len)
|
||||
mvaddchnstr(y+this->selected - this->scrollV, x+0, newRef.chstr + this->scrollH, MIN(newRef.len - scrollH, this->w));
|
||||
RichString_setAttr(&new, highlight);
|
||||
if (scrollH < newLen)
|
||||
RichString_printoffnVal(new, y+this->selected - this->scrollV, x,
|
||||
scrollH, MIN(newLen - scrollH, this->w));
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(new);
|
||||
RichString_end(old);
|
||||
}
|
||||
this->oldSelected = this->selected;
|
||||
move(0, 0);
|
||||
}
|
||||
|
||||
void Panel_onKey(Panel* this, int key) {
|
||||
bool Panel_onKey(Panel* this, int key) {
|
||||
assert (this != NULL);
|
||||
switch (key) {
|
||||
case KEY_DOWN:
|
||||
case KEY_CTRLN:
|
||||
if (this->selected + 1 < Vector_size(this->items))
|
||||
this->selected++;
|
||||
break;
|
||||
return true;
|
||||
case KEY_UP:
|
||||
case KEY_CTRLP:
|
||||
if (this->selected > 0)
|
||||
this->selected--;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if (this->scrollH > 0) {
|
||||
this->scrollH -= this->scrollHAmount;
|
||||
return true;
|
||||
#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;
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
this->scrollH += this->scrollHAmount;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
case KEY_LEFT:
|
||||
case KEY_CTRLB:
|
||||
if (this->scrollH > 0) {
|
||||
this->scrollH -= CRT_scrollHAmount;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
return true;
|
||||
case KEY_RIGHT:
|
||||
case KEY_CTRLF:
|
||||
this->scrollH += CRT_scrollHAmount;
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
case KEY_PPAGE:
|
||||
this->selected -= this->h;
|
||||
this->selected -= (this->h - 1);
|
||||
this->scrollV -= (this->h - 1);
|
||||
if (this->selected < 0)
|
||||
this->selected = 0;
|
||||
break;
|
||||
if (this->scrollV < 0)
|
||||
this->scrollV = 0;
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
case KEY_NPAGE:
|
||||
this->selected += this->h;
|
||||
this->selected += (this->h - 1);
|
||||
int size = Vector_size(this->items);
|
||||
if (this->selected >= size)
|
||||
this->selected = size - 1;
|
||||
break;
|
||||
this->scrollV += (this->h - 1);
|
||||
if (this->scrollV >= MAX(0, size - this->h))
|
||||
this->scrollV = MAX(0, size - this->h - 1);
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
case KEY_HOME:
|
||||
this->selected = 0;
|
||||
break;
|
||||
return true;
|
||||
case KEY_END:
|
||||
this->selected = Vector_size(this->items) - 1;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
61
Panel.h
61
Panel.h
@ -4,26 +4,15 @@
|
||||
#define HEADER_Panel
|
||||
/*
|
||||
htop - Panel.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Object.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
|
||||
|
||||
#include "Object.h"
|
||||
#include "Vector.h"
|
||||
|
||||
typedef struct Panel_ Panel;
|
||||
|
||||
@ -33,20 +22,32 @@ typedef enum HandlerResult_ {
|
||||
BREAK_LOOP
|
||||
} HandlerResult;
|
||||
|
||||
#define EVENT_SETSELECTED -1
|
||||
|
||||
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_ {
|
||||
Object super;
|
||||
PanelClass* class;
|
||||
int x, y, w, h;
|
||||
WINDOW* window;
|
||||
Vector* items;
|
||||
int selected;
|
||||
int scrollV, scrollH;
|
||||
int scrollHAmount;
|
||||
int oldSelected;
|
||||
char* eventHandlerBuffer;
|
||||
int scrollV;
|
||||
short scrollH;
|
||||
bool needsRedraw;
|
||||
RichString header;
|
||||
Panel_EventHandler eventHandler;
|
||||
};
|
||||
|
||||
|
||||
@ -57,26 +58,24 @@ struct Panel_ {
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* PANEL_CLASS;
|
||||
#else
|
||||
#define PANEL_CLASS NULL
|
||||
#endif
|
||||
#define KEY_CTRLN 0016 /* control-n key */
|
||||
#define KEY_CTRLP 0020 /* control-p key */
|
||||
#define KEY_CTRLF 0006 /* control-f key */
|
||||
#define KEY_CTRLB 0002 /* control-b key */
|
||||
|
||||
extern PanelClass Panel_class;
|
||||
|
||||
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare);
|
||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type);
|
||||
|
||||
void Panel_delete(Object* cast);
|
||||
|
||||
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner);
|
||||
void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool owner);
|
||||
|
||||
void Panel_done(Panel* this);
|
||||
|
||||
inline void Panel_setRichHeader(Panel* this, RichString header);
|
||||
RichString* Panel_getHeader(Panel* this);
|
||||
|
||||
inline void Panel_setHeader(Panel* this, char* header);
|
||||
|
||||
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh);
|
||||
extern void Panel_setHeader(Panel* this, const char* header);
|
||||
|
||||
void Panel_move(Panel* this, int x, int y);
|
||||
|
||||
@ -102,12 +101,14 @@ void Panel_moveSelectedDown(Panel* this);
|
||||
|
||||
int Panel_getSelectedIndex(Panel* this);
|
||||
|
||||
int Panel_getSize(Panel* this);
|
||||
int Panel_size(Panel* this);
|
||||
|
||||
void Panel_setSelected(Panel* this, int selected);
|
||||
|
||||
void Panel_draw(Panel* this, bool focus);
|
||||
|
||||
void Panel_onKey(Panel* this, int key);
|
||||
bool Panel_onKey(Panel* this, int key);
|
||||
|
||||
HandlerResult Panel_selectByTyping(Panel* this, int ch);
|
||||
|
||||
#endif
|
||||
|
231
Process.h
231
Process.h
@ -4,46 +4,67 @@
|
||||
#define HEADER_Process
|
||||
/*
|
||||
htop - Process.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "ProcessList.h"
|
||||
#include "Object.h"
|
||||
#include "CRT.h"
|
||||
#include "String.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>
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
#endif
|
||||
|
||||
// This works only with glibc 2.1+. On earlier versions
|
||||
// the behavior is similar to have a hardcoded page size.
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) / 1024 )
|
||||
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
|
||||
#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
|
||||
|
||||
#define PROCESS_COMM_LEN 300
|
||||
#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_ {
|
||||
PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME,
|
||||
STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE,
|
||||
STARTSTACK, KSTKESP, KSTKEIP, SIGNAL, BLOCKED, SSIGIGNORE, SIGCATCH, WCHAN, NSWAP, CNSWAP, EXIT_SIGNAL,
|
||||
PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
|
||||
USER, TIME, NLWP, LAST_PROCESSFIELD
|
||||
USER, TIME, NLWP, TGID,
|
||||
#ifdef HAVE_OPENVZ
|
||||
CTID, VPID,
|
||||
#endif
|
||||
#ifdef HAVE_VSERVER
|
||||
VXID,
|
||||
#endif
|
||||
#ifdef HAVE_TASKSTATS
|
||||
RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE,
|
||||
#endif
|
||||
#ifdef HAVE_CGROUP
|
||||
CGROUP,
|
||||
#endif
|
||||
#ifdef HAVE_OOM
|
||||
OOM,
|
||||
#endif
|
||||
IO_PRIORITY,
|
||||
LAST_PROCESSFIELD
|
||||
} ProcessField;
|
||||
|
||||
struct ProcessList_;
|
||||
@ -52,35 +73,86 @@ typedef struct Process_ {
|
||||
Object super;
|
||||
|
||||
struct ProcessList_ *pl;
|
||||
bool updated;
|
||||
|
||||
unsigned int pid;
|
||||
pid_t pid;
|
||||
char* comm;
|
||||
int indent;
|
||||
char state;
|
||||
bool tag;
|
||||
unsigned int ppid;
|
||||
bool showChildren;
|
||||
bool show;
|
||||
pid_t ppid;
|
||||
unsigned int pgrp;
|
||||
unsigned int session;
|
||||
unsigned int tty_nr;
|
||||
unsigned int tpgid;
|
||||
pid_t tgid;
|
||||
int tpgid;
|
||||
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 cminflt;
|
||||
unsigned long int majflt;
|
||||
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
|
||||
long int itrealvalue;
|
||||
unsigned long int starttime;
|
||||
unsigned long int vsize;
|
||||
long int rss;
|
||||
unsigned long int rlim;
|
||||
@ -97,54 +169,71 @@ typedef struct Process_ {
|
||||
unsigned long int nswap;
|
||||
unsigned long int cnswap;
|
||||
#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;
|
||||
|
||||
} Process;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char* PROCESS_CLASS;
|
||||
#else
|
||||
#define PROCESS_CLASS NULL
|
||||
#endif
|
||||
extern const char *Process_fieldNames[];
|
||||
|
||||
extern char *Process_fieldNames[];
|
||||
extern const int Process_fieldFlags[];
|
||||
|
||||
Process* Process_new(struct ProcessList_ *pl);
|
||||
extern const char *Process_fieldTitles[];
|
||||
|
||||
Process* Process_clone(Process* this);
|
||||
|
||||
void Process_delete(Object* cast);
|
||||
void Process_getMaxPid();
|
||||
|
||||
void Process_display(Object* cast, RichString* out);
|
||||
|
||||
void Process_toggleTag(Process* this);
|
||||
|
||||
void Process_setPriority(Process* this, int priority);
|
||||
|
||||
void Process_sendSignal(Process* this, int signal);
|
||||
|
||||
#define ONE_K 1024
|
||||
#define ONE_K 1024L
|
||||
#define ONE_M (ONE_K * ONE_K)
|
||||
#define ONE_G (ONE_M * ONE_K)
|
||||
|
||||
void Process_writeField(Process* this, RichString* str, ProcessField field);
|
||||
#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);
|
||||
|
||||
extern ObjectClass Process_class;
|
||||
|
||||
Process* Process_new(struct ProcessList_ *pl);
|
||||
|
||||
void Process_toggleTag(Process* this);
|
||||
|
||||
bool Process_setPriority(Process* this, int priority);
|
||||
|
||||
bool Process_changePriorityBy(Process* this, size_t delta);
|
||||
|
||||
IOPriority Process_updateIOPriority(Process* this);
|
||||
|
||||
bool Process_setIOPriority(Process* this, IOPriority 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:
|
||||
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_compare(const void* v1, const void* v2);
|
||||
|
||||
char* Process_printField(ProcessField field);
|
||||
|
||||
#endif
|
||||
|
1149
ProcessList.c
1149
ProcessList.c
File diff suppressed because it is too large
Load Diff
175
ProcessList.h
175
ProcessList.h
@ -9,30 +9,11 @@ Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#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>
|
||||
#include "UsersTable.h"
|
||||
#include "Panel.h"
|
||||
#include "Process.h"
|
||||
|
||||
#ifndef PROCDIR
|
||||
#define PROCDIR "/proc"
|
||||
@ -54,48 +35,73 @@ in the source distribution for its full text.
|
||||
#define MAX_READ 2048
|
||||
#endif
|
||||
|
||||
#ifndef PER_PROCESSOR_FIELDS
|
||||
#define PER_PROCESSOR_FIELDS 20
|
||||
#ifndef ProcessList_cpuId
|
||||
#define ProcessList_cpuId(pl, cpu) ((pl)->countCPUsFromZero ? (cpu) : (cpu)+1)
|
||||
#endif
|
||||
|
||||
typedef enum TreeStr_ {
|
||||
TREE_STR_HORZ,
|
||||
TREE_STR_VERT,
|
||||
TREE_STR_RTEE,
|
||||
TREE_STR_BEND,
|
||||
TREE_STR_TEND,
|
||||
TREE_STR_OPEN,
|
||||
TREE_STR_SHUT,
|
||||
TREE_STR_COUNT
|
||||
} TreeStr;
|
||||
|
||||
typedef 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;
|
||||
|
||||
#ifdef DEBUG_PROC
|
||||
typedef int(*vxscanf)(void*, const char*, va_list);
|
||||
#endif
|
||||
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 guestPeriod;
|
||||
} CPUData;
|
||||
|
||||
typedef struct ProcessList_ {
|
||||
const char **treeStr;
|
||||
Vector* processes;
|
||||
Vector* processes2;
|
||||
Hashtable* processTable;
|
||||
Process* prototype;
|
||||
UsersTable* usersTable;
|
||||
|
||||
int processorCount;
|
||||
Panel* panel;
|
||||
int following;
|
||||
uid_t userId;
|
||||
const char* incFilter;
|
||||
Hashtable* pidWhiteList;
|
||||
|
||||
int cpuCount;
|
||||
int totalTasks;
|
||||
int userlandThreads;
|
||||
int kernelThreads;
|
||||
int runningTasks;
|
||||
|
||||
// Must match number of PER_PROCESSOR_FIELDS constant
|
||||
unsigned long long int* totalTime;
|
||||
unsigned long long int* userTime;
|
||||
unsigned long long int* systemTime;
|
||||
unsigned long long int* systemAllTime;
|
||||
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* 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;
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
hwloc_topology_t topology;
|
||||
bool topologyOk;
|
||||
#endif
|
||||
CPUData* cpus;
|
||||
|
||||
unsigned long long int totalMem;
|
||||
unsigned long long int usedMem;
|
||||
@ -107,63 +113,76 @@ typedef struct ProcessList_ {
|
||||
unsigned long long int usedSwap;
|
||||
unsigned long long int freeSwap;
|
||||
|
||||
int flags;
|
||||
ProcessField* fields;
|
||||
ProcessField sortKey;
|
||||
int direction;
|
||||
bool hideThreads;
|
||||
bool shadowOtherUsers;
|
||||
bool showThreadNames;
|
||||
bool showingThreadNames;
|
||||
bool hideKernelThreads;
|
||||
bool hideUserlandThreads;
|
||||
bool treeView;
|
||||
bool highlightBaseName;
|
||||
bool highlightMegabytes;
|
||||
bool expandSystemTime;
|
||||
#ifdef DEBUG_PROC
|
||||
FILE* traceFile;
|
||||
#endif
|
||||
bool highlightThreads;
|
||||
bool detailedCPUTime;
|
||||
bool countCPUsFromZero;
|
||||
bool updateProcessNames;
|
||||
bool accountGuestInCPUMeter;
|
||||
bool userOnly;
|
||||
|
||||
} ProcessList;
|
||||
|
||||
#ifdef DEBUG_PROC
|
||||
|
||||
#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_treeStrAscii[TREE_STR_COUNT];
|
||||
|
||||
#else
|
||||
extern const char *ProcessList_treeStrUtf8[TREE_STR_COUNT];
|
||||
|
||||
#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);
|
||||
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList);
|
||||
|
||||
void ProcessList_delete(ProcessList* this);
|
||||
|
||||
void ProcessList_setPanel(ProcessList* this, Panel* panel);
|
||||
|
||||
void ProcessList_invertSortOrder(ProcessList* this);
|
||||
|
||||
RichString ProcessList_printHeader(ProcessList* this);
|
||||
void ProcessList_printHeader(ProcessList* this, RichString* header);
|
||||
|
||||
|
||||
void ProcessList_prune(ProcessList* this);
|
||||
|
||||
void ProcessList_add(ProcessList* this, Process* p);
|
||||
|
||||
void ProcessList_remove(ProcessList* this, Process* p);
|
||||
|
||||
Process* ProcessList_get(ProcessList* this, int index);
|
||||
Process* ProcessList_get(ProcessList* this, int idx);
|
||||
|
||||
int ProcessList_size(ProcessList* this);
|
||||
|
||||
void ProcessList_sort(ProcessList* this);
|
||||
|
||||
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name);
|
||||
#ifdef HAVE_TASKSTATS
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENVZ
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CGROUP
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VSERVER
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OOM
|
||||
|
||||
#endif
|
||||
|
||||
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period);
|
||||
|
||||
void ProcessList_scan(ProcessList* this);
|
||||
|
||||
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
|
||||
|
28
README
28
README
@ -1,11 +1,17 @@
|
||||
|
||||
htop
|
||||
by Hisham Muhammad <loderunner@users.sourceforge.net>
|
||||
====
|
||||
|
||||
May, 2004 - July, 2006
|
||||
by Hisham Muhammad <hisham@gobolinux.org>
|
||||
|
||||
May, 2004 - January, 2014
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
 **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
|
||||
~~~~~~~~~~~~
|
||||
------------
|
||||
|
||||
This is htop, an interactive process viewer.
|
||||
It requires ncurses. It is tested with Linux 2.6,
|
||||
@ -15,13 +21,15 @@ with the 2.4 series.
|
||||
Note that, while, htop is Linux specific -- it is based
|
||||
on the Linux /proc filesystem -- it is also reported to work
|
||||
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 months,
|
||||
This software has evolved considerably during the last years,
|
||||
and is reasonably complete, but there is still room for
|
||||
improvement. Read the TODO file to see what's known to be missing.
|
||||
|
||||
Comparison between 'htop' and 'top'
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-----------------------------------
|
||||
|
||||
* In 'htop' you can scroll the list vertically and horizontally
|
||||
to see all processes and full command lines.
|
||||
@ -38,11 +46,15 @@ Comparison between 'htop' and 'top'
|
||||
* 'top' is older, hence, more tested.
|
||||
|
||||
Compilation instructions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
------------------------
|
||||
|
||||
This program is distributed as a standard autotools-based package.
|
||||
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'
|
||||
inside htop) for a list of supported key commands.
|
||||
|
169
RichString.c
169
RichString.c
@ -1,23 +1,59 @@
|
||||
/*
|
||||
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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curses.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define RICHSTRING_MAXLEN 300
|
||||
|
||||
/*{
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define RichString_init(this) (this)->len = 0
|
||||
#define RichString_initVal(this) (this).len = 0
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_NCURSESW_CURSES_H
|
||||
#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
|
||||
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr)
|
||||
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n)
|
||||
#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255)
|
||||
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
|
||||
#define CharType cchar_t
|
||||
#else
|
||||
#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr)
|
||||
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n)
|
||||
#define RichString_getCharVal(this, i) ((this).chptr[i])
|
||||
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
|
||||
#define CharType chtype
|
||||
#endif
|
||||
|
||||
typedef struct RichString_ {
|
||||
int len;
|
||||
chtype chstr[RICHSTRING_MAXLEN+1];
|
||||
int chlen;
|
||||
CharType chstr[RICHSTRING_MAXLEN+1];
|
||||
CharType* chptr;
|
||||
} RichString;
|
||||
|
||||
}*/
|
||||
@ -26,42 +62,113 @@ typedef struct RichString_ {
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
void RichString_write(RichString* this, int attrs, char* data) {
|
||||
RichString_init(this);
|
||||
RichString_append(this, attrs, data);
|
||||
#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;
|
||||
}
|
||||
|
||||
inline void RichString_append(RichString* this, int attrs, char* data) {
|
||||
RichString_appendn(this, attrs, data, strlen(data));
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
|
||||
static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
wchar_t data[len+1];
|
||||
len = mbstowcs(data, data_c, len);
|
||||
if (len<0)
|
||||
return;
|
||||
int newLen = from + len;
|
||||
RichString_setLen(this, newLen);
|
||||
memset(&this->chptr[from], 0, sizeof(CharType) * (newLen - from));
|
||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||
this->chptr[i].chars[0] = data[j];
|
||||
this->chptr[i].attr = attrs;
|
||||
}
|
||||
this->chptr[newLen].chars[0] = 0;
|
||||
}
|
||||
|
||||
inline void RichString_appendn(RichString* this, int attrs, char* data, int len) {
|
||||
int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
|
||||
for (int i = this->len, j = 0; i < last; i++, j++)
|
||||
this->chstr[i] = data[j] | attrs;
|
||||
this->chstr[last] = 0;
|
||||
this->len = last;
|
||||
inline void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
||||
cchar_t* ch = this->chptr + start;
|
||||
for (int i = start; i <= finish; i++) {
|
||||
ch->attr = attrs;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
void RichString_setAttr(RichString *this, int attrs) {
|
||||
chtype* ch = this->chstr;
|
||||
for (int i = 0; i < this->len; i++) {
|
||||
int RichString_findChar(RichString* this, char c, int start) {
|
||||
wchar_t wc = btowc(c);
|
||||
cchar_t* ch = this->chptr + start;
|
||||
for (int i = start; i < this->chlen; i++) {
|
||||
if (ch->chars[0] == wc)
|
||||
return i;
|
||||
ch++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
int newLen = from + len;
|
||||
RichString_setLen(this, newLen);
|
||||
for (int i = from, j = 0; i < newLen; i++, j++)
|
||||
this->chptr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs;
|
||||
this->chptr[newLen] = 0;
|
||||
}
|
||||
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
||||
chtype* ch = this->chptr + start;
|
||||
for (int i = start; i <= finish; i++) {
|
||||
*ch = (*ch & 0xff) | attrs;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
void RichString_applyAttr(RichString *this, int attrs) {
|
||||
chtype* ch = this->chstr;
|
||||
for (int i = 0; i < this->len; i++) {
|
||||
*ch |= attrs;
|
||||
int RichString_findChar(RichString* this, char c, int start) {
|
||||
chtype* ch = this->chptr + start;
|
||||
for (int i = start; i < this->chlen; i++) {
|
||||
if ((*ch & 0xff) == (chtype) c)
|
||||
return i;
|
||||
ch++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
RichString RichString_quickString(int attrs, char* data) {
|
||||
RichString str;
|
||||
RichString_initVal(str);
|
||||
RichString_write(&str, attrs, data);
|
||||
return str;
|
||||
#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) {
|
||||
RichString_setAttrn(this, attrs, 0, this->chlen - 1);
|
||||
}
|
||||
|
||||
void RichString_append(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFrom(this, attrs, data, this->chlen, strlen(data));
|
||||
}
|
||||
|
||||
void RichString_appendn(RichString* this, int attrs, const char* data, int len) {
|
||||
RichString_writeFrom(this, attrs, data, this->chlen, len);
|
||||
}
|
||||
|
||||
void RichString_write(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFrom(this, attrs, data, 0, strlen(data));
|
||||
}
|
||||
|
80
RichString.h
80
RichString.h
@ -2,24 +2,56 @@
|
||||
|
||||
#ifndef HEADER_RichString
|
||||
#define HEADER_RichString
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curses.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
/*
|
||||
htop - RichString.h
|
||||
(C) 2004,2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#define RICHSTRING_MAXLEN 300
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define RichString_init(this) (this)->len = 0
|
||||
#define RichString_initVal(this) (this).len = 0
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_NCURSESW_CURSES_H
|
||||
#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
|
||||
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr)
|
||||
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n)
|
||||
#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255)
|
||||
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
|
||||
#define CharType cchar_t
|
||||
#else
|
||||
#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr)
|
||||
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n)
|
||||
#define RichString_getCharVal(this, i) ((this).chptr[i])
|
||||
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
|
||||
#define CharType chtype
|
||||
#endif
|
||||
|
||||
typedef struct RichString_ {
|
||||
int len;
|
||||
chtype chstr[RICHSTRING_MAXLEN+1];
|
||||
int chlen;
|
||||
CharType chstr[RICHSTRING_MAXLEN+1];
|
||||
CharType* chptr;
|
||||
} RichString;
|
||||
|
||||
|
||||
@ -27,16 +59,30 @@ typedef struct RichString_ {
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
void RichString_write(RichString* this, int attrs, char* data);
|
||||
#define charBytes(n) (sizeof(CharType) * (n))
|
||||
|
||||
inline void RichString_append(RichString* this, int attrs, char* data);
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
|
||||
inline void RichString_appendn(RichString* this, int attrs, char* data, int len);
|
||||
extern void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
||||
|
||||
int RichString_findChar(RichString* this, char c, int start);
|
||||
|
||||
#else
|
||||
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
||||
|
||||
int RichString_findChar(RichString* this, char c, int start);
|
||||
|
||||
#endif
|
||||
|
||||
void RichString_prune(RichString* this);
|
||||
|
||||
void RichString_setAttr(RichString* this, int attrs);
|
||||
|
||||
void RichString_applyAttr(RichString *this, int attrs);
|
||||
void RichString_append(RichString* this, int attrs, const char* data);
|
||||
|
||||
RichString RichString_quickString(int attrs, char* data);
|
||||
void RichString_appendn(RichString* this, int attrs, const char* data, int len);
|
||||
|
||||
void RichString_write(RichString* this, int attrs, const char* data);
|
||||
|
||||
#endif
|
||||
|
123
ScreenManager.c
123
ScreenManager.c
@ -1,22 +1,24 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - ScreenManager.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 "ScreenManager.h"
|
||||
|
||||
#include "Panel.h"
|
||||
#include "Object.h"
|
||||
#include "Vector.h"
|
||||
#include "FunctionBar.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*{
|
||||
#include "FunctionBar.h"
|
||||
#include "Vector.h"
|
||||
#include "Header.h"
|
||||
|
||||
typedef enum Orientation_ {
|
||||
VERTICAL,
|
||||
@ -29,16 +31,19 @@ typedef struct ScreenManager_ {
|
||||
int x2;
|
||||
int y2;
|
||||
Orientation orientation;
|
||||
Vector* items;
|
||||
Vector* panels;
|
||||
Vector* fuBars;
|
||||
int itemCount;
|
||||
FunctionBar* fuBar;
|
||||
int panelCount;
|
||||
const FunctionBar* fuBar;
|
||||
const Header* header;
|
||||
time_t lastScan;
|
||||
bool owner;
|
||||
bool allowFocusChange;
|
||||
} ScreenManager;
|
||||
|
||||
}*/
|
||||
|
||||
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, bool owner) {
|
||||
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, bool owner) {
|
||||
ScreenManager* this;
|
||||
this = malloc(sizeof(ScreenManager));
|
||||
this->x1 = x1;
|
||||
@ -47,28 +52,30 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori
|
||||
this->y2 = y2;
|
||||
this->fuBar = NULL;
|
||||
this->orientation = orientation;
|
||||
this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
|
||||
this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
|
||||
this->itemCount = 0;
|
||||
this->panels = Vector_new(Class(Panel), owner, DEFAULT_SIZE);
|
||||
this->fuBars = Vector_new(Class(FunctionBar), true, DEFAULT_SIZE);
|
||||
this->panelCount = 0;
|
||||
this->header = header;
|
||||
this->owner = owner;
|
||||
this->allowFocusChange = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
void ScreenManager_delete(ScreenManager* this) {
|
||||
Vector_delete(this->items);
|
||||
Vector_delete(this->panels);
|
||||
Vector_delete(this->fuBars);
|
||||
free(this);
|
||||
}
|
||||
|
||||
inline int ScreenManager_size(ScreenManager* this) {
|
||||
return this->itemCount;
|
||||
return this->panelCount;
|
||||
}
|
||||
|
||||
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) {
|
||||
if (this->orientation == HORIZONTAL) {
|
||||
int lastX = 0;
|
||||
if (this->itemCount > 0) {
|
||||
Panel* last = (Panel*) Vector_get(this->items, this->itemCount - 1);
|
||||
if (this->panelCount > 0) {
|
||||
Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1);
|
||||
lastX = last->x + last->w + 1;
|
||||
}
|
||||
if (size > 0) {
|
||||
@ -79,45 +86,39 @@ void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int
|
||||
Panel_move(item, lastX, this->y1);
|
||||
}
|
||||
// TODO: VERTICAL
|
||||
Vector_add(this->items, item);
|
||||
Vector_add(this->panels, item);
|
||||
if (fuBar)
|
||||
Vector_add(this->fuBars, fuBar);
|
||||
else
|
||||
Vector_add(this->fuBars, FunctionBar_new(0, NULL, NULL, NULL));
|
||||
Vector_add(this->fuBars, FunctionBar_new(NULL, NULL, NULL));
|
||||
if (!this->fuBar && fuBar) this->fuBar = fuBar;
|
||||
item->needsRedraw = true;
|
||||
this->itemCount++;
|
||||
this->panelCount++;
|
||||
}
|
||||
|
||||
Panel* ScreenManager_remove(ScreenManager* this, int index) {
|
||||
assert(this->itemCount > index);
|
||||
Panel* panel = (Panel*) Vector_remove(this->items, index);
|
||||
Vector_remove(this->fuBars, index);
|
||||
Panel* ScreenManager_remove(ScreenManager* this, int idx) {
|
||||
assert(this->panelCount > idx);
|
||||
Panel* panel = (Panel*) Vector_remove(this->panels, idx);
|
||||
Vector_remove(this->fuBars, idx);
|
||||
this->fuBar = NULL;
|
||||
this->itemCount--;
|
||||
this->panelCount--;
|
||||
return panel;
|
||||
}
|
||||
|
||||
void ScreenManager_setFunctionBar(ScreenManager* this, FunctionBar* fuBar) {
|
||||
if (this->owner && this->fuBar)
|
||||
FunctionBar_delete((Object*)this->fuBar);
|
||||
this->fuBar = fuBar;
|
||||
}
|
||||
|
||||
void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->x2 = x2;
|
||||
this->y2 = y2;
|
||||
int items = this->itemCount;
|
||||
int panels = this->panelCount;
|
||||
int lastX = 0;
|
||||
for (int i = 0; i < items - 1; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->items, i);
|
||||
for (int i = 0; i < panels - 1; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||
Panel_resize(panel, panel->w, LINES-y1+y2);
|
||||
Panel_move(panel, lastX, y1);
|
||||
lastX = panel->x + panel->w + 1;
|
||||
}
|
||||
Panel* panel = (Panel*) Vector_get(this->items, items-1);
|
||||
Panel* panel = (Panel*) Vector_get(this->panels, panels-1);
|
||||
Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
|
||||
Panel_move(panel, lastX, y1);
|
||||
}
|
||||
@ -126,17 +127,29 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||
bool quit = false;
|
||||
int focus = 0;
|
||||
|
||||
Panel* panelFocus = (Panel*) Vector_get(this->items, focus);
|
||||
Panel* panelFocus = (Panel*) Vector_get(this->panels, focus);
|
||||
if (this->fuBar)
|
||||
FunctionBar_draw(this->fuBar, NULL);
|
||||
|
||||
this->lastScan = 0;
|
||||
|
||||
int ch = 0;
|
||||
while (!quit) {
|
||||
int items = this->itemCount;
|
||||
for (int i = 0; i < items; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->items, i);
|
||||
int panels = this->panelCount;
|
||||
if (this->header) {
|
||||
time_t now = time(NULL);
|
||||
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);
|
||||
if (i < items) {
|
||||
if (i < panels) {
|
||||
if (this->orientation == HORIZONTAL) {
|
||||
mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
|
||||
}
|
||||
@ -150,7 +163,6 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||
|
||||
ch = getch();
|
||||
|
||||
bool loop = false;
|
||||
if (ch == KEY_MOUSE) {
|
||||
MEVENT mevent;
|
||||
int ok = getmouse(&mevent);
|
||||
@ -158,24 +170,23 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||
if (mevent.y == LINES - 1) {
|
||||
ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x);
|
||||
} else {
|
||||
for (int i = 0; i < this->itemCount; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->items, i);
|
||||
for (int i = 0; i < this->panelCount; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||
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;
|
||||
panelFocus = panel;
|
||||
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
|
||||
loop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loop) continue;
|
||||
|
||||
if (panelFocus->eventHandler) {
|
||||
HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
|
||||
if (Panel_eventHandlerFn(panelFocus)) {
|
||||
HandlerResult result = Panel_eventHandler(panelFocus, ch);
|
||||
if (result == HANDLED) {
|
||||
continue;
|
||||
} else if (result == BREAK_LOOP) {
|
||||
@ -193,20 +204,26 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||
continue;
|
||||
}
|
||||
case KEY_LEFT:
|
||||
case KEY_CTRLB:
|
||||
if (!this->allowFocusChange)
|
||||
break;
|
||||
tryLeft:
|
||||
if (focus > 0)
|
||||
focus--;
|
||||
panelFocus = (Panel*) Vector_get(this->items, focus);
|
||||
if (Panel_getSize(panelFocus) == 0 && focus > 0)
|
||||
panelFocus = (Panel*) Vector_get(this->panels, focus);
|
||||
if (Panel_size(panelFocus) == 0 && focus > 0)
|
||||
goto tryLeft;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
case KEY_CTRLF:
|
||||
case 9:
|
||||
if (!this->allowFocusChange)
|
||||
break;
|
||||
tryRight:
|
||||
if (focus < this->itemCount - 1)
|
||||
if (focus < this->panelCount - 1)
|
||||
focus++;
|
||||
panelFocus = (Panel*) Vector_get(this->items, focus);
|
||||
if (Panel_getSize(panelFocus) == 0 && focus < this->itemCount - 1)
|
||||
panelFocus = (Panel*) Vector_get(this->panels, focus);
|
||||
if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
|
||||
goto tryRight;
|
||||
break;
|
||||
case KEY_F(10):
|
||||
|
@ -3,22 +3,15 @@
|
||||
#ifndef HEADER_ScreenManager
|
||||
#define HEADER_ScreenManager
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - ScreenManager.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 "Object.h"
|
||||
#include "Vector.h"
|
||||
#include "FunctionBar.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "Vector.h"
|
||||
#include "Header.h"
|
||||
|
||||
typedef enum Orientation_ {
|
||||
VERTICAL,
|
||||
@ -31,25 +24,26 @@ typedef struct ScreenManager_ {
|
||||
int x2;
|
||||
int y2;
|
||||
Orientation orientation;
|
||||
Vector* items;
|
||||
Vector* panels;
|
||||
Vector* fuBars;
|
||||
int itemCount;
|
||||
FunctionBar* fuBar;
|
||||
int panelCount;
|
||||
const FunctionBar* fuBar;
|
||||
const Header* header;
|
||||
time_t lastScan;
|
||||
bool owner;
|
||||
bool allowFocusChange;
|
||||
} ScreenManager;
|
||||
|
||||
|
||||
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, bool owner);
|
||||
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, bool owner);
|
||||
|
||||
void ScreenManager_delete(ScreenManager* this);
|
||||
|
||||
inline int ScreenManager_size(ScreenManager* this);
|
||||
extern int ScreenManager_size(ScreenManager* this);
|
||||
|
||||
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size);
|
||||
|
||||
Panel* ScreenManager_remove(ScreenManager* this, int index);
|
||||
|
||||
void ScreenManager_setFunctionBar(ScreenManager* this, FunctionBar* fuBar);
|
||||
Panel* ScreenManager_remove(ScreenManager* this, int idx);
|
||||
|
||||
void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2);
|
||||
|
||||
|
186
Settings.c
186
Settings.c
@ -1,65 +1,38 @@
|
||||
/*
|
||||
htop - Settings.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(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 "String.h"
|
||||
#include "ProcessList.h"
|
||||
#include "Header.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "String.h"
|
||||
#include "Vector.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEFAULT_DELAY 15
|
||||
|
||||
/*{
|
||||
#include "ProcessList.h"
|
||||
#include "Header.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct Settings_ {
|
||||
char* userSettings;
|
||||
ProcessList* pl;
|
||||
Header* header;
|
||||
int colorScheme;
|
||||
bool changed;
|
||||
int delay;
|
||||
bool changed;
|
||||
} Settings;
|
||||
|
||||
}*/
|
||||
|
||||
Settings* Settings_new(ProcessList* pl, Header* header) {
|
||||
Settings* this = malloc(sizeof(Settings));
|
||||
this->pl = pl;
|
||||
this->header = header;
|
||||
char* home;
|
||||
char* rcfile;
|
||||
home = getenv("HOME_ETC");
|
||||
if (!home) home = getenv("HOME");
|
||||
if (!home) home = "";
|
||||
rcfile = getenv("HOMERC");
|
||||
if (!rcfile)
|
||||
this->userSettings = String_cat(home, "/.htoprc");
|
||||
else
|
||||
this->userSettings = String_copy(rcfile);
|
||||
this->colorScheme = 0;
|
||||
this->changed = false;
|
||||
this->delay = DEFAULT_DELAY;
|
||||
bool ok = Settings_read(this, this->userSettings);
|
||||
if (!ok) {
|
||||
this->changed = true;
|
||||
// TODO: how to get SYSCONFDIR correctly through Autoconf?
|
||||
char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
|
||||
ok = Settings_read(this, systemSettings);
|
||||
free(systemSettings);
|
||||
if (!ok) {
|
||||
Header_defaultMeters(this->header);
|
||||
pl->hideKernelThreads = true;
|
||||
pl->highlightMegabytes = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void Settings_delete(Settings* this) {
|
||||
free(this->userSettings);
|
||||
free(this);
|
||||
@ -67,10 +40,10 @@ void Settings_delete(Settings* this) {
|
||||
|
||||
static void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
|
||||
char* trim = String_trim(line);
|
||||
char** ids = String_split(trim, ' ');
|
||||
int nIds;
|
||||
char** ids = String_split(trim, ' ', &nIds);
|
||||
free(trim);
|
||||
int i;
|
||||
for (i = 0; ids[i] != NULL; i++) {
|
||||
for (int i = 0; ids[i]; i++) {
|
||||
Header_createMeter(this->header, ids[i], side);
|
||||
}
|
||||
String_freeArray(ids);
|
||||
@ -78,41 +51,44 @@ static void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
|
||||
|
||||
static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) {
|
||||
char* trim = String_trim(line);
|
||||
char** ids = String_split(trim, ' ');
|
||||
int nIds;
|
||||
char** ids = String_split(trim, ' ', &nIds);
|
||||
free(trim);
|
||||
int i;
|
||||
for (i = 0; ids[i] != NULL; i++) {
|
||||
for (int i = 0; ids[i]; i++) {
|
||||
int mode = atoi(ids[i]);
|
||||
Header_setMode(this->header, i, mode, side);
|
||||
}
|
||||
String_freeArray(ids);
|
||||
}
|
||||
|
||||
bool Settings_read(Settings* this, char* fileName) {
|
||||
// TODO: implement File object and make
|
||||
// file I/O object-oriented.
|
||||
FILE* fd;
|
||||
fd = fopen(fileName, "r");
|
||||
if (fd == NULL) {
|
||||
static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
|
||||
FILE* fd = fopen(fileName, "r");
|
||||
if (!fd)
|
||||
return false;
|
||||
}
|
||||
const int maxLine = 512;
|
||||
|
||||
const int maxLine = 2048;
|
||||
char buffer[maxLine];
|
||||
bool readMeters = false;
|
||||
while (!feof(fd)) {
|
||||
buffer[0] = '\0';
|
||||
fgets(buffer, maxLine, fd);
|
||||
char** option = String_split(buffer, '=');
|
||||
while (fgets(buffer, maxLine, fd)) {
|
||||
int nOptions;
|
||||
char** option = String_split(buffer, '=', &nOptions);
|
||||
if (nOptions < 2) {
|
||||
String_freeArray(option);
|
||||
continue;
|
||||
}
|
||||
if (String_eq(option[0], "fields")) {
|
||||
char* trim = String_trim(option[1]);
|
||||
char** ids = String_split(trim, ' ');
|
||||
int nIds;
|
||||
char** ids = String_split(trim, ' ', &nIds);
|
||||
free(trim);
|
||||
int i, j;
|
||||
for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i] != NULL; i++) {
|
||||
this->pl->flags = 0;
|
||||
for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i]; i++) {
|
||||
// This "+1" is for compatibility with the older enum format.
|
||||
int id = atoi(ids[i]) + 1;
|
||||
if (id > 0 && id < LAST_PROCESSFIELD) {
|
||||
this->pl->fields[j] = id;
|
||||
this->pl->flags |= Process_fieldFlags[id];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@ -133,14 +109,27 @@ bool Settings_read(Settings* this, char* fileName) {
|
||||
this->pl->hideUserlandThreads = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "shadow_other_users")) {
|
||||
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")) {
|
||||
this->pl->highlightBaseName = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "highlight_megabytes")) {
|
||||
this->pl->highlightMegabytes = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "highlight_threads")) {
|
||||
this->pl->highlightThreads = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "header_margin")) {
|
||||
this->header->margin = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "expand_system_time")) {
|
||||
this->pl->expandSystemTime = atoi(option[1]);
|
||||
// Compatibility option.
|
||||
this->pl->detailedCPUTime = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "detailed_cpu_time")) {
|
||||
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")) {
|
||||
this->delay = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "color_scheme")) {
|
||||
@ -164,7 +153,7 @@ bool Settings_read(Settings* this, char* fileName) {
|
||||
}
|
||||
fclose(fd);
|
||||
if (!readMeters) {
|
||||
Header_defaultMeters(this->header);
|
||||
Header_defaultMeters(this->header, cpuCount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -177,9 +166,8 @@ bool Settings_write(Settings* this) {
|
||||
if (fd == NULL) {
|
||||
return false;
|
||||
}
|
||||
fprintf(fd, "# Beware! This file is rewritten every time htop exits.\n");
|
||||
fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\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=");
|
||||
for (int i = 0; this->pl->fields[i]; i++) {
|
||||
// This "-1" is for compatibility with the older enum format.
|
||||
@ -193,11 +181,16 @@ bool Settings_write(Settings* this) {
|
||||
fprintf(fd, "hide_kernel_threads=%d\n", (int) this->pl->hideKernelThreads);
|
||||
fprintf(fd, "hide_userland_threads=%d\n", (int) this->pl->hideUserlandThreads);
|
||||
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_megabytes=%d\n", (int) this->pl->highlightMegabytes);
|
||||
fprintf(fd, "highlight_threads=%d\n", (int) this->pl->highlightThreads);
|
||||
fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView);
|
||||
fprintf(fd, "header_margin=%d\n", (int) this->header->margin);
|
||||
fprintf(fd, "expand_system_time=%d\n", (int) this->pl->expandSystemTime);
|
||||
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, "delay=%d\n", (int) this->delay);
|
||||
fprintf(fd, "left_meters=");
|
||||
@ -221,6 +214,71 @@ bool Settings_write(Settings* this) {
|
||||
fprintf(fd, "right_meter_modes=");
|
||||
for (int i = 0; i < Header_size(this->header, RIGHT_HEADER); i++)
|
||||
fprintf(fd, "%d ", Header_readMeterMode(this->header, i, RIGHT_HEADER));
|
||||
fprintf(fd, "\n");
|
||||
fclose(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
|
||||
Settings* this = malloc(sizeof(Settings));
|
||||
this->pl = pl;
|
||||
this->header = header;
|
||||
char* legacyDotfile = NULL;
|
||||
char* rcfile = getenv("HTOPRC");
|
||||
if (rcfile) {
|
||||
this->userSettings = strdup(rcfile);
|
||||
} else {
|
||||
const char* home = getenv("HOME");
|
||||
if (!home) home = "";
|
||||
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
char* configDir = NULL;
|
||||
char* htopDir = NULL;
|
||||
if (xdgConfigHome) {
|
||||
this->userSettings = String_cat(xdgConfigHome, "/htop/htoprc");
|
||||
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->changed = false;
|
||||
this->delay = DEFAULT_DELAY;
|
||||
bool ok = Settings_read(this, legacyDotfile ? legacyDotfile : this->userSettings, cpuCount);
|
||||
if (ok) {
|
||||
if (legacyDotfile) {
|
||||
// Transition to new location and delete old configuration file
|
||||
if (Settings_write(this))
|
||||
unlink(legacyDotfile);
|
||||
}
|
||||
} else {
|
||||
this->changed = true;
|
||||
// TODO: how to get SYSCONFDIR correctly through Autoconf?
|
||||
char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
|
||||
ok = Settings_read(this, systemSettings, cpuCount);
|
||||
free(systemSettings);
|
||||
if (!ok) {
|
||||
Header_defaultMeters(this->header, cpuCount);
|
||||
pl->hideKernelThreads = true;
|
||||
pl->highlightMegabytes = true;
|
||||
pl->highlightThreads = false;
|
||||
}
|
||||
}
|
||||
free(legacyDotfile);
|
||||
return this;
|
||||
}
|
||||
|
19
Settings.h
19
Settings.h
@ -4,36 +4,31 @@
|
||||
#define HEADER_Settings
|
||||
/*
|
||||
htop - Settings.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "String.h"
|
||||
#include "ProcessList.h"
|
||||
#include "Header.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define DEFAULT_DELAY 15
|
||||
|
||||
#include "ProcessList.h"
|
||||
#include "Header.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct Settings_ {
|
||||
char* userSettings;
|
||||
ProcessList* pl;
|
||||
Header* header;
|
||||
int colorScheme;
|
||||
bool changed;
|
||||
int delay;
|
||||
bool changed;
|
||||
} Settings;
|
||||
|
||||
|
||||
Settings* Settings_new(ProcessList* pl, Header* header);
|
||||
|
||||
void Settings_delete(Settings* this);
|
||||
|
||||
bool Settings_read(Settings* this, char* fileName);
|
||||
|
||||
bool Settings_write(Settings* this);
|
||||
|
||||
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount);
|
||||
|
||||
#endif
|
||||
|
101
SignalItem.c
101
SignalItem.c
@ -1,101 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Signal_delete(Object* cast) {
|
||||
Signal* this = (Signal*)cast;
|
||||
assert (this != NULL);
|
||||
// names are string constants, so we're not deleting them.
|
||||
free(this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
45
SignalItem.h
45
SignalItem.h
@ -1,45 +0,0 @@
|
||||
/* 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
|
||||
|
||||
Signal* Signal_new(char* name, int number);
|
||||
|
||||
void Signal_delete(Object* cast);
|
||||
|
||||
void Signal_display(Object* cast, RichString* out);
|
||||
|
||||
int Signal_getSignalCount();
|
||||
|
||||
Signal** Signal_getSignalTable();
|
||||
|
||||
#endif
|
117
SignalsPanel.c
117
SignalsPanel.c
@ -1,77 +1,72 @@
|
||||
/*
|
||||
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 "SignalsPanel.h"
|
||||
#include "Panel.h"
|
||||
#include "SignalItem.h"
|
||||
#include "SignalsPanel.h"
|
||||
|
||||
#include "ListItem.h"
|
||||
#include "RichString.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*{
|
||||
|
||||
typedef struct SignalsPanel_ {
|
||||
Panel super;
|
||||
|
||||
int state;
|
||||
Signal** signals;
|
||||
} SignalsPanel;
|
||||
typedef struct SignalItem_ {
|
||||
const char* name;
|
||||
int number;
|
||||
} SignalItem;
|
||||
|
||||
}*/
|
||||
|
||||
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;
|
||||
static SignalItem signals[] = {
|
||||
{ .name = " 0 Cancel", .number = 0 },
|
||||
{ .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 },
|
||||
};
|
||||
|
||||
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);
|
||||
Panel* SignalsPanel_new() {
|
||||
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem));
|
||||
for(unsigned int i = 0; i < sizeof(signals)/sizeof(SignalItem); i++)
|
||||
Panel_set(this, i, (Object*) ListItem_new(signals[i].name, signals[i].number));
|
||||
Panel_setHeader(this, "Send signal:");
|
||||
Panel_setSelected(this, 16); // 16th item is SIGTERM
|
||||
return this;
|
||||
}
|
||||
|
||||
void SignalsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
SignalsPanel* this = (SignalsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this->signals);
|
||||
free(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;
|
||||
}
|
||||
|
||||
HandlerResult SignalsPanel_EventHandler(Panel* super, int ch) {
|
||||
SignalsPanel* this = (SignalsPanel*) super;
|
||||
|
||||
int size = Panel_getSize(super);
|
||||
|
||||
if (ch <= 255 && isdigit(ch)) {
|
||||
int signal = ch-48 + this->state;
|
||||
for (int i = 0; i < size; i++)
|
||||
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;
|
||||
}
|
||||
|
@ -2,31 +2,20 @@
|
||||
|
||||
#ifndef HEADER_SignalsPanel
|
||||
#define HEADER_SignalsPanel
|
||||
|
||||
#include "Panel.h"
|
||||
#include "SignalItem.h"
|
||||
#include "RichString.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <ctype.h>
|
||||
/*
|
||||
htop - SignalsPanel.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 SignalsPanel_ {
|
||||
Panel super;
|
||||
|
||||
int state;
|
||||
Signal** signals;
|
||||
} SignalsPanel;
|
||||
typedef struct SignalItem_ {
|
||||
const char* name;
|
||||
int number;
|
||||
} SignalItem;
|
||||
|
||||
|
||||
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h);
|
||||
|
||||
void SignalsPanel_delete(Object* object);
|
||||
|
||||
void SignalsPanel_reset(SignalsPanel* this);
|
||||
|
||||
HandlerResult SignalsPanel_EventHandler(Panel* super, int ch);
|
||||
Panel* SignalsPanel_new();
|
||||
|
||||
#endif
|
||||
|
121
String.c
121
String.c
@ -1,32 +1,25 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - String.c
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "String.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#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_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
|
||||
}*/
|
||||
|
||||
inline void String_delete(char* s) {
|
||||
free(s);
|
||||
}
|
||||
|
||||
inline char* String_copy(char* orig) {
|
||||
return strdup(orig);
|
||||
}
|
||||
|
||||
char* String_cat(char* s1, char* s2) {
|
||||
char* String_cat(const char* s1, const char* s2) {
|
||||
int l1 = strlen(s1);
|
||||
int l2 = strlen(s2);
|
||||
char* out = malloc(l1 + l2 + 1);
|
||||
@ -35,7 +28,7 @@ char* String_cat(char* s1, char* s2) {
|
||||
return out;
|
||||
}
|
||||
|
||||
char* String_trim(char* in) {
|
||||
char* String_trim(const char* in) {
|
||||
while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') {
|
||||
in++;
|
||||
}
|
||||
@ -49,53 +42,6 @@ char* String_trim(char* in) {
|
||||
return out;
|
||||
}
|
||||
|
||||
char* String_copyUpTo(char* orig, char upTo) {
|
||||
int len;
|
||||
|
||||
int origLen = strlen(orig);
|
||||
char* at = strchr(orig, upTo);
|
||||
if (at != NULL)
|
||||
len = at - orig;
|
||||
else
|
||||
len = origLen;
|
||||
char* copy = (char*) malloc(len+1);
|
||||
strncpy(copy, orig, len);
|
||||
copy[len] = '\0';
|
||||
return copy;
|
||||
}
|
||||
|
||||
char* String_sub(char* orig, int from, int to) {
|
||||
char* copy;
|
||||
int len;
|
||||
|
||||
len = strlen(orig);
|
||||
if (to > len)
|
||||
to = len;
|
||||
if (from > len)
|
||||
to = len;
|
||||
len = to-from+1;
|
||||
copy = (char*) malloc(len+1);
|
||||
strncpy(copy, orig+from, len);
|
||||
copy[len] = '\0';
|
||||
return copy;
|
||||
}
|
||||
|
||||
void String_println(char* s) {
|
||||
printf("%s\n", s);
|
||||
}
|
||||
|
||||
void String_print(char* s) {
|
||||
printf("%s", s);
|
||||
}
|
||||
|
||||
void String_printInt(int i) {
|
||||
printf("%i", i);
|
||||
}
|
||||
|
||||
void String_printPointer(void* p) {
|
||||
printf("%p", p);
|
||||
}
|
||||
|
||||
inline int String_eq(const char* s1, const char* s2) {
|
||||
if (s1 == NULL || s2 == NULL) {
|
||||
if (s1 == NULL && s2 == NULL)
|
||||
@ -106,7 +52,8 @@ inline int String_eq(const char* s1, const char* s2) {
|
||||
return (strcmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
char** String_split(char* s, char sep) {
|
||||
char** String_split(const char* s, char sep, int* n) {
|
||||
*n = 0;
|
||||
const int rate = 10;
|
||||
char** out = (char**) malloc(sizeof(char*) * rate);
|
||||
int ctr = 0;
|
||||
@ -121,7 +68,13 @@ char** String_split(char* s, char sep) {
|
||||
ctr++;
|
||||
if (ctr == blocks) {
|
||||
blocks += rate;
|
||||
out = (char**) realloc(out, sizeof(char*) * blocks);
|
||||
char** newOut = (char**) realloc(out, sizeof(char*) * blocks);
|
||||
if (newOut) {
|
||||
out = newOut;
|
||||
} else {
|
||||
blocks -= rate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s += size + 1;
|
||||
}
|
||||
@ -132,8 +85,12 @@ char** String_split(char* s, char sep) {
|
||||
out[ctr] = token;
|
||||
ctr++;
|
||||
}
|
||||
out = realloc(out, sizeof(char*) * (ctr + 1));
|
||||
char** newOut = realloc(out, sizeof(char*) * (ctr + 1));
|
||||
if (newOut) {
|
||||
out = newOut;
|
||||
}
|
||||
out[ctr] = NULL;
|
||||
*n = ctr;
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -144,17 +101,29 @@ void String_freeArray(char** s) {
|
||||
free(s);
|
||||
}
|
||||
|
||||
int String_startsWith_i(char* s, char* match) {
|
||||
return (strncasecmp(s, match, strlen(match)) == 0);
|
||||
char* String_getToken(const char* line, const unsigned short int numMatch) {
|
||||
const unsigned short int len = strlen(line);
|
||||
char inWord = 0;
|
||||
unsigned short int count = 0;
|
||||
char match[50];
|
||||
|
||||
unsigned short int foundCount = 0;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int String_contains_i(char* s, char* match) {
|
||||
int lens = strlen(s);
|
||||
int lenmatch = strlen(match);
|
||||
for (int i = 0; i < lens-lenmatch; i++) {
|
||||
if (strncasecmp(s, match, strlen(match)) == 0)
|
||||
return 1;
|
||||
s++;
|
||||
}
|
||||
return 0;
|
||||
match[foundCount] = '\0';
|
||||
return((char*)strdup(match));
|
||||
}
|
||||
|
41
String.h
41
String.h
@ -3,50 +3,25 @@
|
||||
#ifndef HEADER_String
|
||||
#define HEADER_String
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - String.h
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
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_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
|
||||
|
||||
inline void String_delete(char* s);
|
||||
char* String_cat(const char* s1, const char* s2);
|
||||
|
||||
inline char* String_copy(char* orig);
|
||||
char* String_trim(const char* in);
|
||||
|
||||
char* String_cat(char* s1, char* s2);
|
||||
extern int String_eq(const char* s1, const char* s2);
|
||||
|
||||
char* String_trim(char* in);
|
||||
|
||||
char* String_copyUpTo(char* orig, char upTo);
|
||||
|
||||
char* String_sub(char* orig, int from, int to);
|
||||
|
||||
void String_println(char* s);
|
||||
|
||||
void String_print(char* s);
|
||||
|
||||
void String_printInt(int i);
|
||||
|
||||
void String_printPointer(void* p);
|
||||
|
||||
inline int String_eq(const char* s1, const char* s2);
|
||||
|
||||
char** String_split(char* s, char sep);
|
||||
char** String_split(const char* s, char sep, int* n);
|
||||
|
||||
void String_freeArray(char** s);
|
||||
|
||||
int String_startsWith_i(char* s, char* match);
|
||||
|
||||
int String_contains_i(char* s, char* match);
|
||||
char* String_getToken(const char* line, const unsigned short int numMatch);
|
||||
|
||||
#endif
|
||||
|
74
SwapMeter.c
74
SwapMeter.c
@ -1,56 +1,70 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - SwapMeter.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 "SwapMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "CRT.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>
|
||||
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
#define KILOBYTE 1
|
||||
#define MEGABYTE 1024
|
||||
#define GIGABYTE 1048576
|
||||
|
||||
int SwapMeter_attributes[] = {
|
||||
SWAP
|
||||
};
|
||||
|
||||
MeterType SwapMeter = {
|
||||
.setValues = SwapMeter_setValues,
|
||||
/* 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) {
|
||||
long int usedSwap = this->pl->usedSwap;
|
||||
this->total = this->pl->totalSwap;
|
||||
this->values[0] = usedSwap;
|
||||
|
||||
snprintf(buffer, len, "%ld/%ldMB", (long int) usedSwap / MEGABYTE, (long int) this->total / MEGABYTE);
|
||||
}
|
||||
|
||||
static void SwapMeter_display(Object* cast, RichString* out) {
|
||||
char buffer[50];
|
||||
Meter* this = (Meter*)cast;
|
||||
long int swap = (long int) this->values[0];
|
||||
long int total = (long int) this->total;
|
||||
RichString_write(out, CRT_colors[METER_TEXT], ":");
|
||||
SwapMeter_humanNumber(buffer, &total);
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
SwapMeter_humanNumber(buffer, &swap);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "used:");
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
}
|
||||
|
||||
MeterClass SwapMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = SwapMeter_display,
|
||||
.mode = BAR_METERMODE,
|
||||
.items = 1,
|
||||
},
|
||||
.setValues = SwapMeter_setValues,
|
||||
.defaultMode = BAR_METERMODE,
|
||||
.total = 100.0,
|
||||
.attributes = SwapMeter_attributes,
|
||||
.name = "Swap",
|
||||
.uiName = "Swap",
|
||||
.caption = "Swp"
|
||||
};
|
||||
|
||||
void SwapMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
long int usedSwap = this->pl->usedSwap;
|
||||
this->total = this->pl->totalSwap;
|
||||
this->values[0] = usedSwap;
|
||||
snprintf(buffer, len, "%ld/%ldMB", (long int) usedSwap / 1024, (long int) this->total / 1024);
|
||||
}
|
||||
|
||||
void SwapMeter_display(Object* cast, RichString* out) {
|
||||
char buffer[50];
|
||||
Meter* this = (Meter*)cast;
|
||||
long int swap = (long int) this->values[0];
|
||||
RichString_init(out);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], ":");
|
||||
sprintf(buffer, "%ldM ", (long int) this->total / 1024);
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
sprintf(buffer, "%ldk", swap);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], "used:");
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
}
|
||||
|
24
SwapMeter.h
24
SwapMeter.h
@ -3,31 +3,21 @@
|
||||
#ifndef HEADER_SwapMeter
|
||||
#define HEADER_SwapMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - SwapMeter.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"
|
||||
|
||||
#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>
|
||||
#define KILOBYTE 1
|
||||
#define MEGABYTE 1024
|
||||
#define GIGABYTE 1048576
|
||||
|
||||
extern int SwapMeter_attributes[];
|
||||
|
||||
extern MeterType SwapMeter;
|
||||
|
||||
void SwapMeter_setValues(Meter* this, char* buffer, int len);
|
||||
|
||||
void SwapMeter_display(Object* cast, RichString* out);
|
||||
/* NOTE: Value is in kilobytes */
|
||||
extern MeterClass SwapMeter_class;
|
||||
|
||||
#endif
|
||||
|
18
TODO
18
TODO
@ -1,18 +0,0 @@
|
||||
|
||||
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
|
||||
|
||||
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...
|
76
TasksMeter.c
76
TasksMeter.c
@ -1,49 +1,71 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - TasksMeter.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 "TasksMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "ProcessList.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
int TasksMeter_attributes[] = {
|
||||
TASKS_RUNNING
|
||||
};
|
||||
|
||||
MeterType TasksMeter = {
|
||||
.setValues = TasksMeter_setValues,
|
||||
static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
ProcessList* pl = this->pl;
|
||||
this->total = pl->totalTasks;
|
||||
this->values[0] = pl->runningTasks;
|
||||
snprintf(buffer, len, "%d/%d", (int) this->values[0], (int) this->total);
|
||||
}
|
||||
|
||||
static void TasksMeter_display(Object* cast, RichString* out) {
|
||||
Meter* this = (Meter*)cast;
|
||||
ProcessList* pl = this->pl;
|
||||
char buffer[20];
|
||||
sprintf(buffer, "%d", (int)(this->total - pl->userlandThreads - pl->kernelThreads));
|
||||
RichString_write(out, CRT_colors[METER_VALUE], buffer);
|
||||
int threadValueColor = CRT_colors[METER_VALUE];
|
||||
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]);
|
||||
RichString_append(out, CRT_colors[TASKS_RUNNING], buffer);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], " running");
|
||||
}
|
||||
|
||||
MeterClass TasksMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete,
|
||||
.display = TasksMeter_display,
|
||||
.mode = TEXT_METERMODE,
|
||||
.items = 1,
|
||||
},
|
||||
.setValues = TasksMeter_setValues,
|
||||
.defaultMode = TEXT_METERMODE,
|
||||
.total = 100.0,
|
||||
.attributes = TasksMeter_attributes,
|
||||
.name = "Tasks",
|
||||
.uiName = "Task counter",
|
||||
.caption = "Tasks: "
|
||||
};
|
||||
|
||||
void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
this->total = this->pl->totalTasks;
|
||||
this->values[0] = this->pl->runningTasks;
|
||||
snprintf(buffer, len, "%d/%d", (int) this->values[0], (int) this->total);
|
||||
}
|
||||
|
||||
void TasksMeter_display(Object* cast, RichString* out) {
|
||||
Meter* this = (Meter*)cast;
|
||||
RichString_init(out);
|
||||
char buffer[20];
|
||||
sprintf(buffer, "%d", (int)this->total);
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], " total, ");
|
||||
sprintf(buffer, "%d", (int)this->values[0]);
|
||||
RichString_append(out, CRT_colors[TASKS_RUNNING], buffer);
|
||||
RichString_append(out, CRT_colors[METER_TEXT], " running");
|
||||
}
|
||||
|
16
TasksMeter.h
16
TasksMeter.h
@ -3,26 +3,16 @@
|
||||
#ifndef HEADER_TasksMeter
|
||||
#define HEADER_TasksMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - TasksMeter.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"
|
||||
|
||||
#include "ProcessList.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern int TasksMeter_attributes[];
|
||||
|
||||
extern MeterType TasksMeter;
|
||||
|
||||
void TasksMeter_setValues(Meter* this, char* buffer, int len);
|
||||
|
||||
void TasksMeter_display(Object* cast, RichString* out);
|
||||
extern MeterClass TasksMeter_class;
|
||||
|
||||
#endif
|
||||
|
132
TraceScreen.c
132
TraceScreen.c
@ -5,60 +5,76 @@ Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "TraceScreen.h"
|
||||
|
||||
#include "CRT.h"
|
||||
#include "ProcessList.h"
|
||||
#include "ListItem.h"
|
||||
#include "IncSet.h"
|
||||
#include "String.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "TraceScreen.h"
|
||||
#include "ProcessList.h"
|
||||
#include "Process.h"
|
||||
#include "ListItem.h"
|
||||
#include "Panel.h"
|
||||
#include "FunctionBar.h"
|
||||
#include <signal.h>
|
||||
|
||||
/*{
|
||||
#include "Process.h"
|
||||
#include "Panel.h"
|
||||
#include "FunctionBar.h"
|
||||
|
||||
typedef struct TraceScreen_ {
|
||||
Process* process;
|
||||
Panel* display;
|
||||
FunctionBar* bar;
|
||||
bool tracing;
|
||||
} TraceScreen;
|
||||
|
||||
}*/
|
||||
|
||||
static char* tbFunctions[3] = {"AutoScroll ", "Stop Tracing ", "Done "};
|
||||
static const char* tsFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL};
|
||||
|
||||
static char* tbKeys[3] = {"F4", "F5", "Esc"};
|
||||
static const char* tsKeys[] = {"F3", "F4", "F8", "F9", "Esc"};
|
||||
|
||||
static int tbEvents[3] = {KEY_F(4), KEY_F(5), 27};
|
||||
static int tsEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27};
|
||||
|
||||
TraceScreen* TraceScreen_new(Process* process) {
|
||||
TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen));
|
||||
this->process = process;
|
||||
this->display = Panel_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true, ListItem_compare);
|
||||
this->bar = FunctionBar_new(3, tbFunctions, tbKeys, tbEvents);
|
||||
this->display = Panel_new(0, 1, COLS, LINES-2, false, Class(ListItem));
|
||||
this->tracing = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
void TraceScreen_delete(TraceScreen* this) {
|
||||
Panel_delete((Object*)this->display);
|
||||
FunctionBar_delete((Object*)this->bar);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void TraceScreen_draw(TraceScreen* this) {
|
||||
static void TraceScreen_draw(TraceScreen* this, IncSet* inc) {
|
||||
attrset(CRT_colors[PANEL_HEADER_FOCUS]);
|
||||
mvhline(0, 0, ' ', COLS);
|
||||
mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
|
||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||
FunctionBar_draw(this->bar, NULL);
|
||||
IncSet_drawBar(inc);
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -71,9 +87,11 @@ void TraceScreen_run(TraceScreen* this) {
|
||||
if (child == -1) return;
|
||||
if (child == 0) {
|
||||
dup2(fdpair[1], STDERR_FILENO);
|
||||
fcntl(fdpair[1], F_SETFL, O_NONBLOCK);
|
||||
int ok = fcntl(fdpair[1], F_SETFL, O_NONBLOCK);
|
||||
if (ok != -1) {
|
||||
sprintf(buffer, "%d", this->process->pid);
|
||||
execlp("strace", "strace", "-p", buffer, NULL);
|
||||
}
|
||||
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
|
||||
write(fdpair[1], message, strlen(message));
|
||||
exit(1);
|
||||
@ -82,20 +100,37 @@ void TraceScreen_run(TraceScreen* this) {
|
||||
FILE* strace = fdopen(fdpair[0], "r");
|
||||
Panel* panel = this->display;
|
||||
int fd_strace = fileno(strace);
|
||||
TraceScreen_draw(this);
|
||||
CRT_disableDelay();
|
||||
bool contLine = false;
|
||||
bool follow = false;
|
||||
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) {
|
||||
|
||||
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_ZERO(&fds);
|
||||
// FD_SET(STDIN_FILENO, &fds);
|
||||
FD_SET(fd_strace, &fds);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0; tv.tv_usec = 500;
|
||||
int ready = select(fd_strace+1, &fds, NULL, NULL, &tv);
|
||||
int nread = 0;
|
||||
if (ready > 0)
|
||||
if (ready > 0 && FD_ISSET(fd_strace, &fds))
|
||||
nread = fread(buffer, 1, 1000, strace);
|
||||
if (nread && this->tracing) {
|
||||
char* line = buffer;
|
||||
@ -104,25 +139,24 @@ void TraceScreen_run(TraceScreen* this) {
|
||||
if (buffer[i] == '\n') {
|
||||
buffer[i] = '\0';
|
||||
if (contLine) {
|
||||
ListItem_append((ListItem*)Panel_get(panel,
|
||||
Panel_getSize(panel)-1), line);
|
||||
appendLine(line, lines, panel, incFilter);
|
||||
contLine = false;
|
||||
} else {
|
||||
Panel_add(panel, (Object*) ListItem_new(line, 0));
|
||||
addLine(line, lines, panel, incFilter);
|
||||
}
|
||||
line = buffer+i+1;
|
||||
}
|
||||
}
|
||||
if (line < buffer+nread) {
|
||||
Panel_add(panel, (Object*) ListItem_new(line, 0));
|
||||
addLine(line, lines, panel, incFilter);
|
||||
buffer[nread] = '\0';
|
||||
contLine = true;
|
||||
}
|
||||
if (follow)
|
||||
Panel_setSelected(panel, Panel_getSize(panel)-1);
|
||||
Panel_draw(panel, true);
|
||||
Panel_setSelected(panel, Panel_size(panel)-1);
|
||||
}
|
||||
int ch = getch();
|
||||
}
|
||||
|
||||
if (ch == KEY_MOUSE) {
|
||||
MEVENT mevent;
|
||||
int ok = getmouse(&mevent);
|
||||
@ -132,36 +166,62 @@ void TraceScreen_run(TraceScreen* this) {
|
||||
follow = false;
|
||||
ch = 0;
|
||||
} if (mevent.y == LINES - 1)
|
||||
ch = FunctionBar_synthesizeEvent(this->bar, mevent.x);
|
||||
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(5):
|
||||
this->tracing = !this->tracing;
|
||||
FunctionBar_setLabel(this->bar, KEY_F(5), this->tracing?"Stop Tracing ":"Resume Tracing ");
|
||||
TraceScreen_draw(this);
|
||||
case KEY_HOME:
|
||||
Panel_setSelected(panel, 0);
|
||||
break;
|
||||
case KEY_END:
|
||||
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;
|
||||
case 'f':
|
||||
case KEY_F(4):
|
||||
case KEY_F(8):
|
||||
follow = !follow;
|
||||
if (follow)
|
||||
Panel_setSelected(panel, Panel_getSize(panel)-1);
|
||||
Panel_setSelected(panel, Panel_size(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;
|
||||
case 'q':
|
||||
case 27:
|
||||
case KEY_F(10):
|
||||
looping = false;
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
Panel_resize(panel, COLS, LINES-2);
|
||||
TraceScreen_draw(this);
|
||||
TraceScreen_draw(this, inc);
|
||||
break;
|
||||
default:
|
||||
follow = false;
|
||||
Panel_onKey(panel, ch);
|
||||
}
|
||||
Panel_draw(panel, true);
|
||||
}
|
||||
|
||||
IncSet_delete(inc);
|
||||
FunctionBar_delete((Object*)bar);
|
||||
Vector_delete(lines);
|
||||
|
||||
kill(child, SIGTERM);
|
||||
waitpid(child, NULL, 0);
|
||||
fclose(strace);
|
||||
|
@ -9,26 +9,13 @@ Released under the GNU GPL, see the COPYING file
|
||||
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 "ListItem.h"
|
||||
#include "Panel.h"
|
||||
#include "FunctionBar.h"
|
||||
|
||||
|
||||
typedef struct TraceScreen_ {
|
||||
Process* process;
|
||||
Panel* display;
|
||||
FunctionBar* bar;
|
||||
bool tracing;
|
||||
} TraceScreen;
|
||||
|
||||
@ -37,8 +24,6 @@ TraceScreen* TraceScreen_new(Process* process);
|
||||
|
||||
void TraceScreen_delete(TraceScreen* this);
|
||||
|
||||
void TraceScreen_draw(TraceScreen* this);
|
||||
|
||||
void TraceScreen_run(TraceScreen* this);
|
||||
|
||||
#endif
|
||||
|
@ -1,45 +1,37 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - UptimeMeter.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 "UptimeMeter.h"
|
||||
#include "Meter.h"
|
||||
|
||||
#include "ProcessList.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include <math.h>
|
||||
|
||||
/*{
|
||||
#include "Meter.h"
|
||||
}*/
|
||||
|
||||
int UptimeMeter_attributes[] = {
|
||||
UPTIME
|
||||
};
|
||||
|
||||
MeterType UptimeMeter = {
|
||||
.setValues = UptimeMeter_setValues,
|
||||
.display = NULL,
|
||||
.mode = TEXT_METERMODE,
|
||||
.items = 1,
|
||||
.total = 100.0,
|
||||
.attributes = UptimeMeter_attributes,
|
||||
.name = "Uptime",
|
||||
.uiName = "Uptime",
|
||||
.caption = "Uptime: "
|
||||
};
|
||||
|
||||
void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
double uptime;
|
||||
static void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
double uptime = 0;
|
||||
FILE* fd = fopen(PROCDIR "/uptime", "r");
|
||||
fscanf(fd, "%lf", &uptime);
|
||||
if (fd) {
|
||||
fscanf(fd, "%64lf", &uptime);
|
||||
fclose(fd);
|
||||
}
|
||||
int totalseconds = (int) ceil(uptime);
|
||||
int seconds = totalseconds % 60;
|
||||
int minutes = (totalseconds-seconds) % 3600 / 60;
|
||||
int hours = (totalseconds-seconds-(minutes*60)) % 86400 / 3600;
|
||||
int days = (totalseconds-seconds-(minutes*60)-(hours*3600)) / 86400;
|
||||
int minutes = (totalseconds/60) % 60;
|
||||
int hours = (totalseconds/3600) % 24;
|
||||
int days = (totalseconds/86400);
|
||||
this->values[0] = days;
|
||||
if (days > this->total) {
|
||||
this->total = days;
|
||||
@ -56,3 +48,17 @@ void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
|
||||
}
|
||||
snprintf(buffer, len, "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
MeterClass UptimeMeter_class = {
|
||||
.super = {
|
||||
.extends = Class(Meter),
|
||||
.delete = Meter_delete
|
||||
},
|
||||
.setValues = UptimeMeter_setValues,
|
||||
.defaultMode = TEXT_METERMODE,
|
||||
.total = 100.0,
|
||||
.attributes = UptimeMeter_attributes,
|
||||
.name = "Uptime",
|
||||
.uiName = "Uptime",
|
||||
.caption = "Uptime: "
|
||||
};
|
||||
|
@ -3,24 +3,16 @@
|
||||
#ifndef HEADER_UptimeMeter
|
||||
#define HEADER_UptimeMeter
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - UptimeMeter.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"
|
||||
|
||||
#include "ProcessList.h"
|
||||
|
||||
#include "CRT.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern int UptimeMeter_attributes[];
|
||||
|
||||
extern MeterType UptimeMeter;
|
||||
|
||||
void UptimeMeter_setValues(Meter* this, char* buffer, int len);
|
||||
extern MeterClass UptimeMeter_class;
|
||||
|
||||
#endif
|
||||
|
18
UsersTable.c
18
UsersTable.c
@ -1,23 +1,25 @@
|
||||
/*
|
||||
htop - UsersTable.c
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "UsersTable.h"
|
||||
#include "Hashtable.h"
|
||||
#include "String.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*{
|
||||
#include "Hashtable.h"
|
||||
|
||||
typedef struct UsersTable_ {
|
||||
Hashtable* users;
|
||||
} UsersTable;
|
||||
@ -40,17 +42,13 @@ char* UsersTable_getRef(UsersTable* this, unsigned int uid) {
|
||||
if (name == NULL) {
|
||||
struct passwd* userData = getpwuid(uid);
|
||||
if (userData != NULL) {
|
||||
name = String_copy(userData->pw_name);
|
||||
name = strdup(userData->pw_name);
|
||||
Hashtable_put(this->users, uid, name);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
inline int UsersTable_size(UsersTable* this) {
|
||||
return (Hashtable_size(this->users));
|
||||
}
|
||||
|
||||
inline void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData) {
|
||||
Hashtable_foreach(this->users, f, userData);
|
||||
}
|
||||
|
15
UsersTable.h
15
UsersTable.h
@ -4,21 +4,12 @@
|
||||
#define HEADER_UsersTable
|
||||
/*
|
||||
htop - UsersTable.h
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
(C) 2004-2011 Hisham H. Muhammad
|
||||
Released under the GNU GPL, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#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_ {
|
||||
Hashtable* users;
|
||||
@ -30,8 +21,6 @@ void UsersTable_delete(UsersTable* this);
|
||||
|
||||
char* UsersTable_getRef(UsersTable* this, unsigned int uid);
|
||||
|
||||
inline int UsersTable_size(UsersTable* this);
|
||||
|
||||
inline void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData);
|
||||
extern void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData);
|
||||
|
||||
#endif
|
||||
|
242
Vector.c
242
Vector.c
@ -1,40 +1,38 @@
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Vector.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 "Vector.h"
|
||||
#include "Object.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*{
|
||||
#include "Object.h"
|
||||
|
||||
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)
|
||||
|
||||
#ifndef DEFAULT_SIZE
|
||||
#define DEFAULT_SIZE -1
|
||||
#endif
|
||||
|
||||
typedef void(*Vector_procedure)(void*);
|
||||
|
||||
typedef struct Vector_ {
|
||||
Object **array;
|
||||
Object_Compare compare;
|
||||
ObjectClass* type;
|
||||
int arraySize;
|
||||
int growthRate;
|
||||
int items;
|
||||
char* vectorType;
|
||||
bool owner;
|
||||
} Vector;
|
||||
|
||||
}*/
|
||||
|
||||
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare) {
|
||||
Vector* Vector_new(ObjectClass* type, bool owner, int size) {
|
||||
Vector* this;
|
||||
|
||||
if (size == DEFAULT_SIZE)
|
||||
@ -44,9 +42,8 @@ Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compa
|
||||
this->array = (Object**) calloc(size, sizeof(Object*));
|
||||
this->arraySize = size;
|
||||
this->items = 0;
|
||||
this->vectorType = vectorType_;
|
||||
this->type = type;
|
||||
this->owner = owner;
|
||||
this->compare = compare;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -54,7 +51,7 @@ void Vector_delete(Vector* this) {
|
||||
if (this->owner) {
|
||||
for (int i = 0; i < this->items; i++)
|
||||
if (this->array[i])
|
||||
(this->array[i])->delete(this->array[i]);
|
||||
Object_delete(this->array[i]);
|
||||
}
|
||||
free(this->array);
|
||||
free(this);
|
||||
@ -66,7 +63,7 @@ static inline bool Vector_isConsistent(Vector* this) {
|
||||
assert(this->items <= this->arraySize);
|
||||
if (this->owner) {
|
||||
for (int i = 0; i < this->items; i++)
|
||||
if (this->array[i] && this->array[i]->class != this->vectorType)
|
||||
if (this->array[i] && !Object_isA(this->array[i], this->type))
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
@ -88,137 +85,210 @@ int Vector_count(Vector* this) {
|
||||
|
||||
void Vector_prune(Vector* this) {
|
||||
assert(Vector_isConsistent(this));
|
||||
int i;
|
||||
|
||||
for (i = 0; i < this->items; i++)
|
||||
if (this->owner) {
|
||||
for (int i = 0; i < this->items; i++)
|
||||
if (this->array[i]) {
|
||||
if (this->owner)
|
||||
(this->array[i])->delete(this->array[i]);
|
||||
this->array[i] = NULL;
|
||||
Object_delete(this->array[i]);
|
||||
//this->array[i] = NULL;
|
||||
}
|
||||
}
|
||||
this->items = 0;
|
||||
}
|
||||
|
||||
void Vector_sort(Vector* this) {
|
||||
assert(this->compare);
|
||||
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;
|
||||
static int comparisons = 0;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static void Vector_checkArraySize(Vector* this) {
|
||||
assert(Vector_isConsistent(this));
|
||||
if (this->items >= this->arraySize) {
|
||||
int i;
|
||||
i = this->arraySize;
|
||||
//int i;
|
||||
//i = this->arraySize;
|
||||
this->arraySize = this->items + this->growthRate;
|
||||
this->array = (Object**) realloc(this->array, sizeof(Object*) * this->arraySize);
|
||||
for (; i < this->arraySize; i++)
|
||||
this->array[i] = NULL;
|
||||
//for (; i < this->arraySize; i++)
|
||||
// this->array[i] = NULL;
|
||||
}
|
||||
assert(Vector_isConsistent(this));
|
||||
}
|
||||
|
||||
void Vector_insert(Vector* this, int index, void* data_) {
|
||||
assert(index >= 0);
|
||||
assert(((Object*)data_)->class == this->vectorType);
|
||||
void Vector_insert(Vector* this, int idx, void* data_) {
|
||||
Object* data = data_;
|
||||
assert(idx >= 0);
|
||||
assert(idx <= this->items);
|
||||
assert(Object_isA(data, this->type));
|
||||
assert(Vector_isConsistent(this));
|
||||
|
||||
Vector_checkArraySize(this);
|
||||
assert(this->array[this->items] == NULL);
|
||||
for (int i = this->items; i >= index; i--) {
|
||||
this->array[i+1] = this->array[i];
|
||||
//assert(this->array[this->items] == NULL);
|
||||
for (int i = this->items; i > idx; i--) {
|
||||
this->array[i] = this->array[i-1];
|
||||
}
|
||||
this->array[index] = data;
|
||||
this->array[idx] = data;
|
||||
this->items++;
|
||||
assert(Vector_isConsistent(this));
|
||||
}
|
||||
|
||||
Object* Vector_take(Vector* this, int index) {
|
||||
assert(index >= 0 && index < this->items);
|
||||
Object* Vector_take(Vector* this, int idx) {
|
||||
assert(idx >= 0 && idx < this->items);
|
||||
assert(Vector_isConsistent(this));
|
||||
Object* removed = this->array[index];
|
||||
assert (removed != NULL);
|
||||
Object* removed = this->array[idx];
|
||||
//assert (removed != NULL);
|
||||
this->items--;
|
||||
for (int i = index; i < this->items; i++)
|
||||
for (int i = idx; i < this->items; i++)
|
||||
this->array[i] = this->array[i+1];
|
||||
this->array[this->items] = NULL;
|
||||
//this->array[this->items] = NULL;
|
||||
assert(Vector_isConsistent(this));
|
||||
return removed;
|
||||
}
|
||||
|
||||
Object* Vector_remove(Vector* this, int index) {
|
||||
Object* removed = Vector_take(this, index);
|
||||
Object* Vector_remove(Vector* this, int idx) {
|
||||
Object* removed = Vector_take(this, idx);
|
||||
if (this->owner) {
|
||||
removed->delete(removed);
|
||||
Object_delete(removed);
|
||||
return NULL;
|
||||
} else
|
||||
return removed;
|
||||
}
|
||||
|
||||
void Vector_moveUp(Vector* this, int index) {
|
||||
assert(index >= 0 && index < this->items);
|
||||
void Vector_moveUp(Vector* this, int idx) {
|
||||
assert(idx >= 0 && idx < this->items);
|
||||
assert(Vector_isConsistent(this));
|
||||
if (index == 0)
|
||||
if (idx == 0)
|
||||
return;
|
||||
Object* temp = this->array[index];
|
||||
this->array[index] = this->array[index - 1];
|
||||
this->array[index - 1] = temp;
|
||||
Object* temp = this->array[idx];
|
||||
this->array[idx] = this->array[idx - 1];
|
||||
this->array[idx - 1] = temp;
|
||||
}
|
||||
|
||||
void Vector_moveDown(Vector* this, int index) {
|
||||
assert(index >= 0 && index < this->items);
|
||||
void Vector_moveDown(Vector* this, int idx) {
|
||||
assert(idx >= 0 && idx < this->items);
|
||||
assert(Vector_isConsistent(this));
|
||||
if (index == this->items - 1)
|
||||
if (idx == this->items - 1)
|
||||
return;
|
||||
Object* temp = this->array[index];
|
||||
this->array[index] = this->array[index + 1];
|
||||
this->array[index + 1] = temp;
|
||||
Object* temp = this->array[idx];
|
||||
this->array[idx] = this->array[idx + 1];
|
||||
this->array[idx + 1] = temp;
|
||||
}
|
||||
|
||||
void Vector_set(Vector* this, int index, void* data_) {
|
||||
assert(index >= 0);
|
||||
assert(((Object*)data_)->class == this->vectorType);
|
||||
void Vector_set(Vector* this, int idx, void* data_) {
|
||||
Object* data = data_;
|
||||
assert(idx >= 0);
|
||||
assert(Object_isA((Object*)data, this->type));
|
||||
assert(Vector_isConsistent(this));
|
||||
|
||||
Vector_checkArraySize(this);
|
||||
if (index >= this->items) {
|
||||
this->items = index+1;
|
||||
if (idx >= this->items) {
|
||||
this->items = idx+1;
|
||||
} else {
|
||||
if (this->owner) {
|
||||
Object* removed = this->array[index];
|
||||
Object* removed = this->array[idx];
|
||||
assert (removed != NULL);
|
||||
if (this->owner) {
|
||||
removed->delete(removed);
|
||||
Object_delete(removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->array[index] = data;
|
||||
this->array[idx] = data;
|
||||
assert(Vector_isConsistent(this));
|
||||
}
|
||||
|
||||
inline Object* Vector_get(Vector* this, int index) {
|
||||
assert(index < this->items);
|
||||
#ifdef DEBUG
|
||||
|
||||
inline Object* Vector_get(Vector* this, int idx) {
|
||||
assert(idx < this->items);
|
||||
assert(Vector_isConsistent(this));
|
||||
return this->array[index];
|
||||
return this->array[idx];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define Vector_get(v_, idx_) ((v_)->array[idx_])
|
||||
|
||||
#endif
|
||||
|
||||
inline int Vector_size(Vector* this) {
|
||||
assert(Vector_isConsistent(this));
|
||||
return this->items;
|
||||
}
|
||||
|
||||
void Vector_merge(Vector* this, Vector* v2) {
|
||||
/*
|
||||
|
||||
static void Vector_merge(Vector* this, Vector* v2) {
|
||||
int i;
|
||||
assert(Vector_isConsistent(this));
|
||||
|
||||
@ -229,9 +299,11 @@ void Vector_merge(Vector* this, Vector* v2) {
|
||||
assert(Vector_isConsistent(this));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
void Vector_add(Vector* this, void* data_) {
|
||||
assert(data_ && ((Object*)data_)->class == this->vectorType);
|
||||
Object* data = data_;
|
||||
assert(Object_isA((Object*)data, this->type));
|
||||
assert(Vector_isConsistent(this));
|
||||
int i = this->items;
|
||||
Vector_set(this, this->items, data);
|
||||
@ -240,23 +312,15 @@ void Vector_add(Vector* this, void* data_) {
|
||||
}
|
||||
|
||||
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
|
||||
assert(((Object*)search_)->class == this->vectorType);
|
||||
assert(this->compare);
|
||||
Object* search = search_;
|
||||
assert(Object_isA((Object*)search, this->type));
|
||||
assert(compare);
|
||||
assert(Vector_isConsistent(this));
|
||||
for (int i = 0; i < this->items; i++) {
|
||||
Object* o = (Object*)this->array[i];
|
||||
if (o && compare(search, o) == 0)
|
||||
assert(o);
|
||||
if (compare(search, o) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
59
Vector.h
59
Vector.h
@ -3,39 +3,31 @@
|
||||
#ifndef HEADER_Vector
|
||||
#define HEADER_Vector
|
||||
/*
|
||||
htop
|
||||
(C) 2004-2006 Hisham H. Muhammad
|
||||
htop - Vector.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 "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
|
||||
#define DEFAULT_SIZE -1
|
||||
#endif
|
||||
|
||||
typedef void(*Vector_procedure)(void*);
|
||||
|
||||
typedef struct Vector_ {
|
||||
Object **array;
|
||||
Object_Compare compare;
|
||||
ObjectClass* type;
|
||||
int arraySize;
|
||||
int growthRate;
|
||||
int items;
|
||||
char* vectorType;
|
||||
bool owner;
|
||||
} Vector;
|
||||
|
||||
|
||||
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare);
|
||||
Vector* Vector_new(ObjectClass* type, bool owner, int size);
|
||||
|
||||
void Vector_delete(Vector* this);
|
||||
|
||||
@ -47,30 +39,45 @@ int Vector_count(Vector* this);
|
||||
|
||||
void Vector_prune(Vector* this);
|
||||
|
||||
void Vector_sort(Vector* this);
|
||||
// If I were to use only one sorting algorithm for both cases, it would probably be this one:
|
||||
/*
|
||||
|
||||
void Vector_insert(Vector* this, int index, void* data_);
|
||||
*/
|
||||
|
||||
Object* Vector_take(Vector* this, int index);
|
||||
void Vector_quickSort(Vector* this);
|
||||
|
||||
Object* Vector_remove(Vector* this, int index);
|
||||
void Vector_insertionSort(Vector* this);
|
||||
|
||||
void Vector_moveUp(Vector* this, int index);
|
||||
void Vector_insert(Vector* this, int idx, void* data_);
|
||||
|
||||
void Vector_moveDown(Vector* this, int index);
|
||||
Object* Vector_take(Vector* this, int idx);
|
||||
|
||||
void Vector_set(Vector* this, int index, void* data_);
|
||||
Object* Vector_remove(Vector* this, int idx);
|
||||
|
||||
inline Object* Vector_get(Vector* this, int index);
|
||||
void Vector_moveUp(Vector* this, int idx);
|
||||
|
||||
inline int Vector_size(Vector* this);
|
||||
void Vector_moveDown(Vector* this, int idx);
|
||||
|
||||
void Vector_merge(Vector* this, Vector* v2);
|
||||
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);
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
void Vector_add(Vector* this, void* data_);
|
||||
|
||||
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
|
||||
|
||||
void Vector_foreach(Vector* this, Vector_procedure f);
|
||||
extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
aclocal
|
||||
aclocal -I m4
|
||||
autoconf
|
||||
autoheader
|
||||
libtoolize --copy --force
|
||||
automake --add-missing --copy
|
||||
|
||||
|
||||
|
121
configure.ac
121
configure.ac
@ -1,33 +1,36 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([htop],[0.6.6],[loderunner@users.sourceforge.net])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_PREREQ(2.65)
|
||||
AC_INIT([htop],[1.0.3],[hisham@gobolinux.org])
|
||||
|
||||
# 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_HEADER([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
AC_DISABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"])
|
||||
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.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([stdlib.h string.h strings.h sys/param.h sys/time.h unistd.h curses.h],[:],[
|
||||
AC_CHECK_HEADERS([stdlib.h string.h strings.h sys/param.h sys/time.h unistd.h],[:],[
|
||||
missing_headers="$missing_headers $ac_header"
|
||||
])
|
||||
|
||||
if test ! -z "$missing_headers"; then
|
||||
AC_MSG_ERROR([missing headers: $missing_headers])
|
||||
fi
|
||||
AC_CHECK_HEADERS([execinfo.h],[:],[:])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
@ -37,17 +40,17 @@ AC_TYPE_UID_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_CLOSEDIR_VOID
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_REALLOC
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_STAT
|
||||
AC_CHECK_FUNCS([memmove strncasecmp strstr strdup])
|
||||
|
||||
save_cflags="${CFLAGS}"
|
||||
CFLAGS="${CFLAGS} -std=c99"
|
||||
AC_MSG_CHECKING([whether gcc -std=c99 option works])
|
||||
AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [char *a; a = strdup("foo"); int i = 0; i++; // C99],
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_ERROR([htop is written in C99. A newer version of gcc is required.]))
|
||||
CFLAGS="$save_cflags"
|
||||
|
||||
PROCDIR=/proc
|
||||
AC_ARG_WITH(proc, [ --with-proc=DIR Location of a Linux-compatible proc filesystem (default=/proc).],
|
||||
@ -58,8 +61,94 @@ AC_ARG_WITH(proc, [ --with-proc=DIR Location of a Linux-compatible proc fi
|
||||
fi,
|
||||
AC_DEFINE(PROCDIR, "/proc", [Path of proc filesystem]))
|
||||
|
||||
AC_ARG_ENABLE(openvz, [AC_HELP_STRING([--enable-openvz], [enable OpenVZ support])], ,enable_openvz="no")
|
||||
if test "x$enable_openvz" = xyes; then
|
||||
AC_DEFINE(HAVE_OPENVZ, 1, [Define if openvz support enabled.])
|
||||
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")
|
||||
if test "x$enable_taskstats" = xyes; then
|
||||
AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes")
|
||||
if test "x$enable_unicode" = xyes; then
|
||||
AC_CHECK_LIB([ncursesw], [refresh], [], [
|
||||
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
|
||||
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
|
||||
|
||||
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/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.))
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
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")
|
||||
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
|
||||
|
28
debug.h
28
debug.h
@ -1,28 +0,0 @@
|
||||
|
||||
#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
|
||||
|
120
htop.1
120
htop.1
@ -1,120 +0,0 @@
|
||||
.TH "htop" "1" "0.6.6" "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 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
Normal file
333
htop.1.in
Normal file
@ -0,0 +1,333 @@
|
||||
.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.
|
@ -1,12 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Version=0.6.6
|
||||
Version=1.0
|
||||
Name=Htop
|
||||
Type=Application
|
||||
Comment=Show System Processes
|
||||
Terminal=true
|
||||
Exec=htop
|
||||
Path=
|
||||
Icon=htop
|
||||
Categories=ConsoleOnly;System;Application;
|
||||
Categories=ConsoleOnly;System;
|
||||
GenericName=Process Viewer
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user