124 Commits
0.6.2 ... 0.8.2

Author SHA1 Message Date
4c8bc0158a Add missing file. 2009-06-02 19:32:54 +00:00
f87877273f Add missing file. 2009-06-02 19:31:49 +00:00
54bdb472b3 Tag release 0.8.2 in revision history. 2009-06-02 19:24:33 +00:00
4488caa70a Tempus Fugit. 2009-06-02 05:07:08 +00:00
9b8d11d9f1 doc fix 2009-06-02 05:06:20 +00:00
6330ff3a0a changes for htop 0.8.2 2009-06-02 04:51:23 +00:00
1371ee28a7 don't use unbounded operations 2009-06-02 04:49:26 +00:00
b62f9cea6f improve man-page 2009-06-02 04:29:26 +00:00
20bb68824d updated battery meter code from Ian Hands, slightly tweaked 2009-04-27 21:48:09 +00:00
510213591b clean inc search buffer code 2009-04-22 19:26:49 +00:00
843aded57c sort by PROCESSOR and SESSION 2009-03-11 13:52:39 +00:00
31b3a2d2db catch nonprintable characters 2009-03-11 13:51:50 +00:00
385a7dbe1e simplify uptime calculation 2009-03-11 13:26:39 +00:00
3b950e4189 BSD related fixes:
* 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)
2009-03-11 13:15:43 +00:00
b93e5c00b6 Rename VEID to CTID in OpenVZ systems
(thanks to Thorsten Schifferdecker)
2009-03-11 13:05:19 +00:00
10213f3ea1 improve help on monochrome, fix bug #2430855 2009-02-18 00:34:18 +00:00
f2ef3b74a0 * corrections to the desktop entry file
(thanks by Samuli Suominen)
2009-02-18 00:06:18 +00:00
ac5cecb6fc Option to display hostname in the meters area 2009-02-17 18:33:32 +00:00
c3d682b0f6 fix bug #2171752 2009-02-17 18:13:25 +00:00
dc38fc2da3 Fix missing tree view when userland threads are hidden
(thanks to Josh Stone)
2009-02-17 17:12:59 +00:00
0baba6d7b4 Fix for VPID on OpenVZ systems
(thanks to Wolfgang Frisch)
2009-02-17 15:36:43 +00:00
a2f6eea0c4 Remove assertion that fails on hardened kernels
(thanks to Wolfram Schlich for the report)
2008-09-23 06:29:03 +00:00
11931f1bc8 ACPI Battery meter
contributed by Ian Hands
2008-09-23 06:21:28 +00:00
c3550e18e8 Avoid reading process IO info multiple times on multithreaded processes.
Bugfix from Gerhard Heift.
2008-09-23 05:56:15 +00:00
a5dfaa2393 Add Linux-VServer support,
contributed by Jonathan Sambrook and Benedikt Bohm
2008-09-23 04:31:13 +00:00
6beb27d803 Prepare for release 0.8 2008-05-07 23:02:38 +00:00
ce3114079c Fix mouseclick handling in top bar 2008-05-07 23:02:23 +00:00
15ab0ad706 Let mouseclicks tick/untick checkboxes 2008-05-07 23:01:45 +00:00
23615d63a8 Make setup screen fully mouse-driveable 2008-04-23 07:24:27 +00:00
b09339d643 Enabling taskstats by default since they don't break
on systems that don't have them.
2008-03-16 00:31:31 +00:00
2338ad5820 Ability to change sort column with the mouse by
clicking column titles (click again to invert order).
Also, add a consolidated IO kbyte/s column.
2008-03-14 18:50:49 +00:00
fa6f919059 Add missing bits to build system, needed by the inclusion of PLPA.
Thanks to Bert Wesarg for the heads up.
2008-03-11 19:22:17 +00:00
da23c8c5a1 Clean up headers by using 'static' whenever possible.
Reduces resulting code size.
2008-03-09 08:58:38 +00:00
12f4f09e6e 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!
2008-03-09 08:02:22 +00:00
460608d6e2 Make column operation more comfortable. 2008-03-09 07:42:19 +00:00
8fa33dc336 Add Unicode support, enabled with the --enable-unicode
flag, which requires libncursesw.
Thanks to Sergej Pupykin!
2008-03-09 02:33:23 +00:00
fa87ff0251 Clean up htop's configure options. 2008-03-09 02:16:21 +00:00
93f091c47e 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)
Also, add option to display thread colors differently.
2008-03-08 23:39:48 +00:00
52840406ac Make sure help screen is properly filled.
Make behavior of H key consistent.
2008-03-08 23:30:35 +00:00
4df76d127b Embed PLPA (Portable Linux Processor Affinity) in order to support
conflicting affinity API of different Linux kernel versions.
2008-03-05 09:46:47 +00:00
5ed2b85c84 Make clicks on leftmost panel in the Setup screen change setup pages,
like the keyboard navigation does. Fixes bug reported by Tero Keinanen.
https://sourceforge.net/tracker/index.php?func=detail&aid=1754735&group_id=108839&atid=651633
2008-03-05 06:54:30 +00:00
062433fe04 Time keeps passing by 2008-03-05 06:52:22 +00:00
657b0f5efc Time keeps passing by 2008-03-05 06:51:32 +00:00
37bb2fc5c7 Fix display of time with the "Black on White" theme. 2008-03-05 06:39:29 +00:00
cf7fdcd1d6 Experimental feature: beep on permission failures.
Update dates.
2007-12-17 05:57:28 +00:00
a839c3f2ca Adding affinity panel 2007-12-17 05:50:00 +00:00
807df03671 Avoid crashing when using many meters (thanks to David Cho for the report) 2007-11-26 22:06:25 +00:00
bd0f30dcd6 Getting things ready for a release 2007-11-23 17:56:29 +00:00
855d9eaf9a 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)
2007-11-09 00:40:59 +00:00
b70b35ea65 Improve error display on crash to get better bug reports. 2007-11-08 23:53:03 +00:00
a7c2aedcec Improve construction of tree view, properly nesting threads.
Add CPU affinity screen ('a' key).
BUGFIX: Correct display of TPGID field.
Add TGID field.
2007-11-08 23:23:01 +00:00
46631b59fb Add reminder on a bug 2007-08-10 06:31:31 +00:00
e3acb5e07a Add a trailing newline in .htoprc
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=420856
(sheesh, the things people get worked up about :) )
2007-08-10 06:26:39 +00:00
5a91824e46 update changelog 2007-08-10 06:17:09 +00:00
f356997269 Fix crash on invalid command line arguments:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=435651
2007-08-10 06:13:13 +00:00
e685bdeea0 Fix GCC 4.3 issues: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=416852 2007-08-10 05:59:36 +00:00
4c51ad0e35 OpenVZ support, contributed by Sergey Lychko 2007-08-10 05:07:14 +00:00
d357c67717 Add support of NLWP field, by Bert Wesarg 2007-05-21 19:10:53 +00:00
e1a7e2bdef Fix regeneration of headers 2007-05-21 19:09:19 +00:00
d2f767e607 Getting things ready for a next release 2007-05-17 18:46:40 +00:00
b1e9d716f2 keep debug code up-to-date 2007-05-17 18:44:57 +00:00
6271138237 update changelog 2007-05-17 18:44:37 +00:00
255c62a460 update changelog 2007-05-17 18:31:00 +00:00
9710a43001 Fixes for /proc location, submitted by Florent Thoumie 2007-05-17 18:29:30 +00:00
df20abfd67 Rule for automatically rebuilding headers 2007-05-17 18:28:20 +00:00
d46dcf99fd Make process memory percentage calculation saner. 2007-04-10 16:27:12 +00:00
f56c8014f7 Apply patches by Matthias Lederhofer adding extra
memory status fields
2007-04-05 20:13:32 +00:00
a227b20fef Switch to unsigned keys in hash, according to issue #1688290
in the sf tracker
2007-04-05 19:53:23 +00:00
e3198ca63b Fix gcc warning. 2006-11-29 18:35:25 +00:00
92a5a691fd Report change suggested by Bo Liu 2006-11-20 16:46:20 +00:00
6b6b4373b5 Changes suggested by Bo Liu 2006-11-20 16:42:03 +00:00
2a025bf4c6 Add information about the status column
(which I always forget) in the help page
2006-11-16 15:20:44 +00:00
14808f7f70 Getting ready for 0.6.5... 2006-11-14 17:24:09 +00:00
a26ef71ed8 Minor tweak. 2006-11-13 22:04:17 +00:00
a8f45d5743 Sanity cleanup. 2006-11-13 22:00:16 +00:00
9076b9edeb Add latest changes to the log 2006-11-13 21:59:01 +00:00
0f027ded2c Fix for missing libraries message, as reported by Jon 780 2006-11-13 20:06:31 +00:00
3d62edb678 Bugfix: collect orphaned items during tree generation
at the end of the tree.
Add debugging sanity checks.
2006-11-12 21:53:56 +00:00
36848494f5 Add debugging sanity checks. 2006-11-12 21:52:14 +00:00
c90a445103 Don't double-free comm when it's an existingProcess 2006-11-09 01:44:20 +00:00
97ea7a1a8c Ok, second take on fixing the handling of comm.- 2006-11-08 22:16:46 +00:00
adbfe82e63 Oops. 2006-11-08 22:09:13 +00:00
45fab61da3 Avoid double free of prototype's comm. 2006-11-08 22:08:00 +00:00
8adc7ac00f Fix asserts, don't use freed memory. 2006-11-08 21:49:52 +00:00
2713119249 Add missing header. 2006-11-08 21:49:07 +00:00
59c3dd806b Yet another sanity check. 2006-11-08 21:47:11 +00:00
c494308b21 Add an additional debug mode for Hardened GCC. 2006-11-08 21:46:40 +00:00
c4fbd7fc8b Assign creation of the allocation log file to a separate #define. 2006-11-08 20:40:10 +00:00
febe259e91 Add lots of debugging asserts and try to clean up behavior of lists in general.
Make dumping of proc data controlled by a separate debug define.
2006-11-08 20:12:57 +00:00
110ce71b9b Add consistency checks. 2006-11-08 20:09:48 +00:00
46b35b2c7f Initialize variable. 2006-11-08 20:09:12 +00:00
b25ac6b0f7 Handle situation instead of assuming it would never happen,
as it was seen out in the field and tested here.
2006-10-26 23:06:52 +00:00
649419abe5 Prepare for next release 2006-10-04 16:42:15 +00:00
2c4d730403 Allocate per-processor values in a contiguous chunk of memory 2006-10-04 16:25:41 +00:00
538d29b3f6 Add changelog entry for Philipp Richter's contribution 2006-10-04 14:48:03 +00:00
3e4f06d101 Contribution by Philipp Richter: Display IO-Wait, IRQ and Soft-IRQ values in status bar
(minor modifications: default to false, add help)
2006-10-04 14:21:27 +00:00
4a93a7e962 changelog entry for Marc's bugfix 2006-08-30 04:38:53 +00:00
ef5b27f33a A fix for long uptimes, sent my Marc Cahalan 2006-08-30 04:37:20 +00:00
cc5af25e11 Fix bug 1538463. 2006-08-24 21:28:29 +00:00
b10821aae9 --sort-key flag in the command-line, overriding the
saved setting in .htoprc for the session.
(thanks to Rodolfo Borges)
2006-08-04 20:54:37 +00:00
bf44e233e6 No longer untag processes after sending a signal
(useful for when SIGTERM fails and one wants to try again
with SIGKILL).
2006-07-23 22:57:25 +00:00
2ecf199cf7 Horizontally scroll in larger increments when on the
Linux console because of slow update of unaccelerated fb
2006-07-23 22:45:24 +00:00
eb2803ce79 Share name strings from UsersList 2006-07-12 01:35:59 +00:00
dbe2670b69 Perform RichString operations by hand.
Avoid unnecessary operations when processing entries on ProcessList.
2006-07-12 01:16:03 +00:00
e46f1426b9 Make checks for headers and libraries actually halt configure. 2006-07-12 01:15:14 +00:00
3bf904b7ce Bringing extra files up-to-date 2006-07-12 01:14:48 +00:00
07030b4518 Minor update to the README file. 2006-07-11 06:20:33 +00:00
5d48ab8c28 Performance improvement hackathon: improve process comparison routines,
disable useless code in release builds such as runtime type-checking on
dynamic data structures and process fields that are not being computed,
faster(?) method for verifying the process owner (still need to ensure
correctness), don't destroy and create process objects for hidden kernel
threads over and over. Phew. I shouldn't be doing all this today, but I
could not resist.
2006-07-11 06:13:32 +00:00
4c41e78bbf Standardize on sourceforge address for htop information. 2006-07-11 00:34:39 +00:00
646f174d26 Bring TODO file back from the dead 2006-07-01 22:52:39 +00:00
2f1f82ee87 Updates for new version of the MakeHeader.py script. 2006-06-06 20:41:01 +00:00
b95993fa22 More information in debug output. 2006-06-06 20:40:29 +00:00
f6e0b7d0c0 Regenerated all headers. 2006-06-06 20:28:42 +00:00
35afc13ebf New version of MakeHeader. Does not use 'private' comment annotation,
using the 'static' storage class instead. Automatically generates
'extern' declarations in headers for non-static data.
2006-06-06 20:28:09 +00:00
5d07013e83 These were merged into LoadAverageMeter.[ch] 2006-06-06 20:14:34 +00:00
8c643f5f89 Use long long types to avoid overflow 2006-06-05 21:28:54 +00:00
d0325cfec5 Disable old hack that's interfering with real debugging. 2006-06-05 15:53:16 +00:00
8bc180b7d1 Display error message when strace is not available.
Mark autogen.sh executable in svn.
2006-06-03 23:14:09 +00:00
57bd892b37 Add "debuglite" mode. 2006-05-30 14:26:30 +00:00
9da282d748 Remove references to ListBox 2006-05-30 14:02:43 +00:00
ea855aef73 Remove references to ListBox 2006-05-30 14:00:18 +00:00
73de9f1ed4 Rename ListBox'es to Panel's, matching dit. 2006-05-30 13:52:12 +00:00
c2cdcd0c1d Rename ListBox to Panel, matching dit. 2006-05-30 13:47:28 +00:00
a853faaa2d Rename TypedVector to Vector, matching dit. 2006-05-30 13:45:40 +00:00
127 changed files with 8013 additions and 3412 deletions

49
AffinityPanel.c Normal file
View File

@ -0,0 +1,49 @@
#include "AffinityPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "debug.h"
#include <assert.h>
static HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) {
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) Panel_getSelected(this);
switch(ch) {
case KEY_MOUSE:
case ' ':
CheckItem_set(selected, ! (CheckItem_get(selected)) );
result = HANDLED;
break;
case 0x0a:
case 0x0d:
case KEY_ENTER:
result = BREAK_LOOP;
break;
}
return result;
}
Panel* AffinityPanel_new(int processorCount, unsigned long mask) {
Panel* this = Panel_new(1, 1, 1, 1, CHECKITEM_CLASS, true, ListItem_compare);
this->eventHandler = AffinityPanel_eventHandler;
Panel_setHeader(this, "Use CPUs:");
for (int i = 0; i < processorCount; i++) {
char number[10];
snprintf(number, 9, "%d", i+1);
Panel_add(this, (Object*) CheckItem_new(String_copy(number), NULL, mask & (1 << i)));
}
return this;
}
unsigned long AffinityPanel_getAffinity(Panel* this) {
int size = Panel_size(this);
unsigned long mask = 0;
for (int i = 0; i < size; i++) {
if (CheckItem_get((CheckItem*)Panel_get(this, i)))
mask = mask | (1 << i);
}
return mask;
}

17
AffinityPanel.h Normal file
View File

@ -0,0 +1,17 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AffinityPanel
#define HEADER_AffinityPanel
#include "Panel.h"
#include "CheckItem.h"
#include "debug.h"
#include <assert.h>
Panel* AffinityPanel_new(int processorCount, unsigned long mask);
unsigned long AffinityPanel_getAffinity(Panel* this);
#endif

View File

@ -1,72 +0,0 @@
#include "AvailableColumnsListBox.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ColumnsListBox.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct AvailableColumnsListBox_ {
ListBox super;
ListBox* columns;
Settings* settings;
ScreenManager* scr;
} AvailableColumnsListBox;
}*/
AvailableColumnsListBox* AvailableColumnsListBox_new(Settings* settings, ListBox* columns, ScreenManager* scr) {
AvailableColumnsListBox* this = (AvailableColumnsListBox*) malloc(sizeof(AvailableColumnsListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableColumnsListBox_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = AvailableColumnsListBox_eventHandler;
ListBox_setHeader(super, "Available Columns");
for (int i = 1; i < LAST_PROCESSFIELD; i++) {
if (i != COMM)
ListBox_add(super, (Object*) ListItem_new(Process_fieldNames[i], 0));
}
this->columns = columns;
return this;
}
void AvailableColumnsListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
AvailableColumnsListBox* this = (AvailableColumnsListBox*) object;
ListBox_done(super);
free(this);
}
HandlerResult AvailableColumnsListBox_eventHandler(ListBox* super, int ch) {
AvailableColumnsListBox* this = (AvailableColumnsListBox*) super;
char* text = ((ListItem*) ListBox_getSelected(super))->value;
HandlerResult result = IGNORED;
switch(ch) {
case 13:
case KEY_ENTER:
case KEY_F(5):
{
int at = ListBox_getSelectedIndex(this->columns) + 1;
if (at == ListBox_getSize(this->columns))
at--;
ListBox_insert(this->columns, at, (Object*) ListItem_new(text, 0));
ColumnsListBox_update(this->columns);
result = HANDLED;
break;
}
}
return result;
}

View File

@ -1,31 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_AvailableColumnsListBox
#define HEADER_AvailableColumnsListBox
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableColumnsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
ListBox* columns;
} AvailableColumnsListBox;
AvailableColumnsListBox* AvailableColumnsListBox_new(Settings* settings, ListBox* columns, ScreenManager* scr);
void AvailableColumnsListBox_delete(Object* object);
HandlerResult AvailableColumnsListBox_eventHandler(ListBox* super, int ch);
#endif

71
AvailableColumnsPanel.c Normal file
View File

@ -0,0 +1,71 @@
#include "AvailableColumnsPanel.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
Settings* settings;
ScreenManager* scr;
} 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;
}
}
return result;
}
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr) {
AvailableColumnsPanel* this = (AvailableColumnsPanel*) malloc(sizeof(AvailableColumnsPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableColumnsPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = AvailableColumnsPanel_eventHandler;
Panel_setHeader(super, "Available Columns");
for (int i = 1; i < LAST_PROCESSFIELD; i++) {
if (i != COMM)
Panel_add(super, (Object*) ListItem_new(Process_fieldNames[i], 0));
}
this->columns = columns;
return this;
}

28
AvailableColumnsPanel.h Normal file
View File

@ -0,0 +1,28 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableColumnsPanel
#define HEADER_AvailableColumnsPanel
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
Settings* settings;
ScreenManager* scr;
} AvailableColumnsPanel;
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr);
#endif

View File

@ -1,106 +0,0 @@
#include "AvailableMetersListBox.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct AvailableMetersListBox_ {
ListBox super;
Settings* settings;
ListBox* leftBox;
ListBox* rightBox;
ScreenManager* scr;
} AvailableMetersListBox;
}*/
AvailableMetersListBox* AvailableMetersListBox_new(Settings* settings, ListBox* leftMeters, ListBox* rightMeters, ScreenManager* scr) {
AvailableMetersListBox* this = (AvailableMetersListBox*) malloc(sizeof(AvailableMetersListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableMetersListBox_delete;
this->settings = settings;
this->leftBox = leftMeters;
this->rightBox = rightMeters;
this->scr = scr;
super->eventHandler = AvailableMetersListBox_EventHandler;
ListBox_setHeader(super, "Available meters");
for (int i = 1; Meter_types[i]; i++) {
MeterType* type = Meter_types[i];
if (type != &CPUMeter) {
ListBox_add(super, (Object*) ListItem_new(type->uiName, i << 16));
}
}
MeterType* type = &CPUMeter;
int processors = settings->pl->processorCount;
if (processors > 1) {
ListBox_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);
ListBox_add(super, (Object*) ListItem_new(buffer, i));
}
} else {
ListBox_add(super, (Object*) ListItem_new("CPU", 1));
}
return this;
}
void AvailableMetersListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
AvailableMetersListBox* this = (AvailableMetersListBox*) object;
ListBox_done(super);
free(this);
}
/* private */
inline void AvailableMetersListBox_addHeader(Header* header, ListBox* lb, MeterType* type, int param, HeaderSide side) {
Meter* meter = (Meter*) Header_addMeter(header, type, param, side);
ListBox_add(lb, (Object*) Meter_toListItem(meter));
}
HandlerResult AvailableMetersListBox_EventHandler(ListBox* super, int ch) {
AvailableMetersListBox* this = (AvailableMetersListBox*) super;
Header* header = this->settings->header;
ListItem* selected = (ListItem*) ListBox_getSelected(super);
int param = selected->key & 0xff;
int type = selected->key >> 16;
HandlerResult result = IGNORED;
switch(ch) {
case KEY_F(5):
case 'l':
case 'L':
{
AvailableMetersListBox_addHeader(header, this->leftBox, Meter_types[type], param, LEFT_HEADER);
result = HANDLED;
break;
}
case KEY_F(6):
case 'r':
case 'R':
{
AvailableMetersListBox_addHeader(header, this->rightBox, Meter_types[type], param, RIGHT_HEADER);
result = HANDLED;
break;
}
}
if (result == HANDLED) {
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;
}

View File

@ -1,33 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_AvailableMetersListBox
#define HEADER_AvailableMetersListBox
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableMetersListBox_ {
ListBox super;
Settings* settings;
ListBox* leftBox;
ListBox* rightBox;
ScreenManager* scr;
} AvailableMetersListBox;
AvailableMetersListBox* AvailableMetersListBox_new(Settings* settings, ListBox* leftMeters, ListBox* rightMeters, ScreenManager* scr);
void AvailableMetersListBox_delete(Object* object);
HandlerResult AvailableMetersListBox_EventHandler(ListBox* super, int ch);
#endif

106
AvailableMetersPanel.c Normal file
View File

@ -0,0 +1,106 @@
#include "AvailableMetersPanel.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "CPUMeter.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct AvailableMetersPanel_ {
Panel super;
Settings* settings;
Panel* leftPanel;
Panel* rightPanel;
ScreenManager* scr;
} AvailableMetersPanel;
}*/
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) {
Meter* meter = (Meter*) Header_addMeter(header, type, param, side);
Panel_add(panel, (Object*) Meter_toListItem(meter));
}
static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
AvailableMetersPanel* this = (AvailableMetersPanel*) super;
Header* header = this->settings->header;
ListItem* selected = (ListItem*) Panel_getSelected(super);
int param = selected->key & 0xff;
int type = selected->key >> 16;
HandlerResult result = IGNORED;
switch(ch) {
case KEY_F(5):
case 'l':
case 'L':
{
AvailableMetersPanel_addHeader(header, this->leftPanel, Meter_types[type], param, LEFT_HEADER);
result = HANDLED;
break;
}
case KEY_F(6):
case 'r':
case 'R':
{
AvailableMetersPanel_addHeader(header, this->rightPanel, Meter_types[type], param, RIGHT_HEADER);
result = HANDLED;
break;
}
}
if (result == HANDLED) {
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;
}
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;
}

29
AvailableMetersPanel.h Normal file
View File

@ -0,0 +1,29 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableMetersPanel
#define HEADER_AvailableMetersPanel
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "CPUMeter.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableMetersPanel_ {
Panel super;
Settings* settings;
Panel* leftPanel;
Panel* rightPanel;
ScreenManager* scr;
} AvailableMetersPanel;
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr);
#endif

331
BatteryMeter.c Normal file
View File

@ -0,0 +1,331 @@
/*
htop
(C) 2004-2006 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 "Meter.h"
#include "ProcessList.h"
#include "CRT.h"
#include "String.h"
#include "debug.h"
/*{
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
}*/
int BatteryMeter_attributes[] = {
BATTERY
};
static unsigned long int parseUevent(FILE * file, char *key) {
char line[100];
unsigned long int dValue = 0;
while (fgets(line, sizeof line, file)) {
if (strncmp(line, key, strlen(key)) == 0) {
char *value;
value = strtok(line, "=");
value = strtok(NULL, "=");
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 DIR *batteryDir;
const struct dirent *dirEntries;
const char batteryPath[] = PROCDIR "/acpi/battery/";
batteryDir = opendir(batteryPath);
if (batteryDir == NULL) {
return 0;
}
char *entryName;
typedef struct listLbl {
char *content;
struct listLbl *next;
} list;
list *myList = NULL;
list *newEntry;
/*
Some of this is based off of code found in kismet (they claim it came from gkrellm).
Written for multi battery use...
*/
for (dirEntries = readdir((DIR *) batteryDir); dirEntries; dirEntries = readdir((DIR *) batteryDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "BAT", 3))
continue;
newEntry = calloc(1, sizeof(list));
newEntry->next = myList;
newEntry->content = entryName;
myList = newEntry;
}
unsigned long int total = 0;
for (newEntry = myList; newEntry; newEntry = newEntry->next) {
const char infoPath[30];
const FILE *file;
char line[50];
snprintf((char *) infoPath, sizeof infoPath, "%s%s/%s", batteryPath, newEntry->content, fileName);
if ((file = fopen(infoPath, "r")) == NULL) {
return 0;
}
for (unsigned short int i = 0; i < lineNum; i++) {
fgets(line, sizeof line, (FILE *) file);
}
fclose((FILE *) file);
const char *foundNumTmp = String_getToken(line, wordNum);
const unsigned long int foundNum = atoi(foundNumTmp);
free((char *) foundNumTmp);
total += foundNum;
}
free(myList);
free(newEntry);
closedir((DIR *) batteryDir);
return total;
}
static ACPresence chkIsOnline() {
FILE *file = NULL;
ACPresence isOn = AC_ERROR;
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
const struct dirent *dirEntries;
char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
DIR *power_supplyDir = opendir(power_supplyPath);
char *entryName;
if (!power_supplyDir) {
closedir(power_supplyDir);
return AC_ERROR;
}
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "A", 1)) {
continue;
}
char statePath[50];
snprintf((char *) statePath, sizeof statePath, "%s/%s/state", power_supplyPath, entryName);
file = fopen(statePath, "r");
if (!file) {
isOn = AC_ERROR;
continue;
}
char line[100];
fgets(line, sizeof line, file);
line[sizeof(line) - 1] = '\0';
if (file) {
fclose(file);
file = NULL;
}
const char *isOnline = String_getToken(line, 2);
if (strcmp(isOnline, "on-line") == 0) {
free((char *) isOnline);
isOn = AC_PRESENT;
// If any AC adapter is being used then stop
break;
} else {
isOn = AC_ABSENT;
}
free((char *) isOnline);
}
if (power_supplyDir)
closedir(power_supplyDir);
} else {
char *power_supplyPath = "/sys/class/power_supply";
if (access("/sys/class/power_supply", F_OK) == 0) {
const struct dirent *dirEntries;
DIR *power_supplyDir = opendir(power_supplyPath);
char *entryName;
if (!power_supplyDir) {
return AC_ERROR;
}
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "A", 1)) {
continue;
}
char onlinePath[50];
snprintf((char *) onlinePath, sizeof onlinePath, "%s/%s/online", power_supplyPath, entryName);
file = fopen(onlinePath, "r");
if (!file) {
isOn = AC_ERROR;
continue;
}
isOn = (fgetc(file) - '0');
if (file) {
fclose(file);
file = NULL;
}
if (isOn == AC_PRESENT) {
// If any AC adapter is being used then stop
break;
} else {
continue;
}
}
if (power_supplyDir)
closedir(power_supplyDir);
}
}
// Just in case :-)
if (file)
fclose(file);
return isOn;
}
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;
double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
return percent;
}
static double getSysBatData() {
const struct dirent *dirEntries;
char *power_supplyPath = "/sys/class/power_supply/";
DIR *power_supplyDir = opendir(power_supplyPath);
if (!power_supplyDir) {
closedir(power_supplyDir);
return 0;
}
char *entryName;
unsigned long int totalFull = 0;
unsigned long int totalRemain = 0;
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->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;
}
totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL=");
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
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;
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;
}
MeterType BatteryMeter = {
.setValues = BatteryMeter_setValues,
.display = NULL,
.mode = TEXT_METERMODE,
.items = 1,
.total = 100.0,
.attributes = BatteryMeter_attributes,
.name = "Battery",
.uiName = "Battery",
.caption = "Battery: "
};

View File

@ -18,15 +18,131 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
/* private property */ int CPUMeter_attributes[] = {
static int CPUMeter_attributes[] = { CPU_NICE, CPU_NORMAL, CPU_KERNEL }; CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_IOWAIT
};
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
static void CPUMeter_init(Meter* this) {
int processor = this->param;
if (this->pl->processorCount > 1) {
char caption[10];
sprintf(caption, "%-3d", processor);
Meter_setCaption(this, caption);
}
if (this->param == 0)
Meter_setCaption(this, "Avg");
}
static void CPUMeter_setValues(Meter* this, char* buffer, int size) {
ProcessList* pl = this->pl;
int processor = this->param;
if (processor > this->pl->processorCount) {
snprintf(buffer, size, "absent");
return;
}
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->detailedCPUTime) {
this->values[2] = pl->systemPeriod[processor] / total * 100.0;
this->values[3] = pl->irqPeriod[processor] / total * 100.0;
this->values[4] = pl->softIrqPeriod[processor] / total * 100.0;
this->values[5] = pl->ioWaitPeriod[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])));
} 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])));
}
snprintf(buffer, size, "%5.1f%%", cpu );
}
static void CPUMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
RichString_init(out);
if (this->param > this->pl->processorCount) {
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->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);
sprintf(buffer, "%5.1f%% ", this->values[3]);
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);
sprintf(buffer, "%5.1f%% ", this->values[5]);
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);
}
}
static 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;
this->mode = BAR_METERMODE;
}
static void AllCPUsMeter_done(Meter* this) {
int processors = this->pl->processorCount;
Meter** meters = (Meter**) this->drawBuffer;
for (int i = 0; i < processors; i++)
Meter_delete((Object*)meters[i]);
}
static void AllCPUsMeter_setMode(Meter* this, int mode) {
this->mode = mode;
int processors = this->pl->processorCount;
int h = Meter_modes[this->mode]->h;
this->h = h * processors;
}
static 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);
meters[i]->draw(meters[i], x, y, w);
y += meters[i]->h;
}
}
/* private */
MeterType CPUMeter = { MeterType CPUMeter = {
.setValues = CPUMeter_setValues, .setValues = CPUMeter_setValues,
.display = CPUMeter_display, .display = CPUMeter_display,
.mode = BAR_METERMODE, .mode = BAR_METERMODE,
.items = 3, .items = 6,
.total = 100.0, .total = 100.0,
.attributes = CPUMeter_attributes, .attributes = CPUMeter_attributes,
.name = "CPU", .name = "CPU",
@ -35,7 +151,6 @@ MeterType CPUMeter = {
.init = CPUMeter_init .init = CPUMeter_init
}; };
/* private */
MeterType AllCPUsMeter = { MeterType AllCPUsMeter = {
.mode = 0, .mode = 0,
.items = 1, .items = 1,
@ -49,81 +164,3 @@ MeterType AllCPUsMeter = {
.setMode = AllCPUsMeter_setMode, .setMode = AllCPUsMeter_setMode,
.done = AllCPUsMeter_done .done = AllCPUsMeter_done
}; };
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
void CPUMeter_init(Meter* this) {
int processor = this->param;
if (this->pl->processorCount > 1) {
char caption[10];
sprintf(caption, "%-3d", processor);
Meter_setCaption(this, caption);
}
if (this->param == 0)
Meter_setCaption(this, "Avg");
}
void CPUMeter_setValues(Meter* this, char* buffer, int size) {
ProcessList* pl = this->pl;
int processor = this->param;
double total = (double) pl->totalPeriod[processor];
this->values[0] = pl->nicePeriod[processor] / total * 100.0;
this->values[1] = pl->userPeriod[processor] / total * 100.0;
this->values[2] = pl->systemPeriod[processor] / total * 100.0;
double cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2])));
snprintf(buffer, size, "%5.1f%%", cpu );
}
void CPUMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
RichString_prune(out);
sprintf(buffer, "%5.1f%% ", this->values[1]);
RichString_append(out, CRT_colors[METER_TEXT], ":");
RichString_append(out, CRT_colors[CPU_NORMAL], buffer);
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);
}
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;
this->mode = BAR_METERMODE;
}
void AllCPUsMeter_done(Meter* this) {
int processors = this->pl->processorCount;
Meter** meters = (Meter**) this->drawBuffer;
for (int i = 0; i < processors; i++)
Meter_delete((Object*)meters[i]);
}
void AllCPUsMeter_setMode(Meter* this, int mode) {
this->mode = mode;
int processors = this->pl->processorCount;
int h = Meter_modes[this->mode]->h;
this->h = h * processors;
}
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);
meters[i]->draw(meters[i], x, y, w);
y += meters[i]->h;
}
}

View File

@ -3,7 +3,7 @@
#ifndef HEADER_CPUMeter #ifndef HEADER_CPUMeter
#define HEADER_CPUMeter #define HEADER_CPUMeter
/* /*
htop - CPUMeter.c htop - CPUMeter.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -21,8 +21,7 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
extern int CPUMeter_attributes[];
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
@ -31,18 +30,8 @@ in the source distribution for its full text.
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
void CPUMeter_init(Meter* this); extern MeterType CPUMeter;
void CPUMeter_setValues(Meter* this, char* buffer, int size); extern MeterType AllCPUsMeter;
void CPUMeter_display(Object* cast, RichString* out);
void AllCPUsMeter_init(Meter* this);
void AllCPUsMeter_done(Meter* this);
void AllCPUsMeter_setMode(Meter* this, int mode);
void AllCPUsMeter_draw(Meter* this, int x, int y, int w);
#endif #endif

106
CRT.c
View File

@ -14,6 +14,7 @@ in the source distribution for its full text.
#include "String.h" #include "String.h"
#include "config.h"
#include "debug.h" #include "debug.h"
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j) #define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
@ -55,6 +56,7 @@ typedef enum ColorElements_ {
METER_VALUE, METER_VALUE,
LED_COLOR, LED_COLOR,
UPTIME, UPTIME,
BATTERY,
TASKS_TOTAL, TASKS_TOTAL,
TASKS_RUNNING, TASKS_RUNNING,
SWAP, SWAP,
@ -67,6 +69,8 @@ typedef enum ColorElements_ {
PROCESS_BASENAME, PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY, PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY, PROCESS_LOW_PRIORITY,
PROCESS_THREAD,
PROCESS_THREAD_BASENAME,
BAR_BORDER, BAR_BORDER,
BAR_SHADOW, BAR_SHADOW,
GRAPH_1, GRAPH_1,
@ -93,27 +97,35 @@ typedef enum ColorElements_ {
CPU_NORMAL, CPU_NORMAL,
CPU_KERNEL, CPU_KERNEL,
HELP_BOLD, HELP_BOLD,
CPU_IOWAIT,
CPU_IRQ,
CPU_SOFTIRQ,
HOSTNAME,
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
extern int CRT_delay;
extern int CRT_colors[LAST_COLORELEMENT];
extern int CRT_colorScheme;
}*/ }*/
// TODO: centralize these in Settings. // TODO: centralize these in Settings.
/* private property */ int CRT_delay = 0;
int CRT_delay;
/* private property */ int CRT_colorScheme = 0;
int CRT_colorScheme;
/* private property */ int CRT_colors[LAST_COLORELEMENT] = { 0 };
int CRT_colors[LAST_COLORELEMENT];
char* CRT_termType;
static void CRT_handleSIGSEGV(int signal) {
CRT_done();
fprintf(stderr, "htop " VERSION " aborted. Please report bug at http://htop.sf.net\n");
exit(1);
}
static void CRT_handleSIGTERM(int signal) {
CRT_done();
exit(0);
}
// TODO: pass an instance of Settings instead. // TODO: pass an instance of Settings instead.
@ -133,8 +145,8 @@ void CRT_init(int delay, int colorScheme) {
} else { } else {
CRT_hasColors = false; CRT_hasColors = false;
} }
char* termType = getenv("TERM"); CRT_termType = getenv("TERM");
if (String_eq(termType, "xterm") || String_eq(termType, "xterm-color") || String_eq(termType, "vt220")) { if (String_eq(CRT_termType, "xterm") || String_eq(CRT_termType, "xterm-color") || String_eq(CRT_termType, "vt220")) {
define_key("\033[H", KEY_HOME); define_key("\033[H", KEY_HOME);
define_key("\033[F", KEY_END); define_key("\033[F", KEY_END);
define_key("\033OP", KEY_F(1)); define_key("\033OP", KEY_F(1));
@ -167,6 +179,7 @@ void CRT_done() {
int CRT_readKey() { int CRT_readKey() {
nocbreak(); nocbreak();
cbreak(); cbreak();
nodelay(stdscr, FALSE);
int ret = getch(); int ret = getch();
halfdelay(CRT_delay); halfdelay(CRT_delay);
return ret; return ret;
@ -182,17 +195,6 @@ void CRT_enableDelay() {
halfdelay(CRT_delay); 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);
}
void CRT_setColors(int colorScheme) { void CRT_setColors(int colorScheme) {
CRT_colorScheme = colorScheme; CRT_colorScheme = colorScheme;
if (colorScheme == COLORSCHEME_BLACKNIGHT) { if (colorScheme == COLORSCHEME_BLACKNIGHT) {
@ -212,10 +214,11 @@ void CRT_setColors(int colorScheme) {
CRT_colors[FUNCTION_KEY] = A_NORMAL; CRT_colors[FUNCTION_KEY] = A_NORMAL;
CRT_colors[PANEL_HEADER_FOCUS] = A_REVERSE; CRT_colors[PANEL_HEADER_FOCUS] = A_REVERSE;
CRT_colors[PANEL_HEADER_UNFOCUS] = A_REVERSE; CRT_colors[PANEL_HEADER_UNFOCUS] = A_REVERSE;
CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE | A_BOLD; CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE;
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_REVERSE; CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD;
CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD; CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD;
CRT_colors[UPTIME] = A_BOLD; CRT_colors[UPTIME] = A_BOLD;
CRT_colors[BATTERY] = A_BOLD;
CRT_colors[LARGE_NUMBER] = A_BOLD; CRT_colors[LARGE_NUMBER] = A_BOLD;
CRT_colors[METER_TEXT] = A_NORMAL; CRT_colors[METER_TEXT] = A_NORMAL;
CRT_colors[METER_VALUE] = A_BOLD; CRT_colors[METER_VALUE] = A_BOLD;
@ -230,6 +233,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = A_BOLD; CRT_colors[PROCESS_R_STATE] = A_BOLD;
CRT_colors[PROCESS_HIGH_PRIORITY] = A_BOLD; CRT_colors[PROCESS_HIGH_PRIORITY] = A_BOLD;
CRT_colors[PROCESS_LOW_PRIORITY] = A_DIM; 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_BORDER] = A_BOLD;
CRT_colors[BAR_SHADOW] = A_DIM; CRT_colors[BAR_SHADOW] = A_DIM;
CRT_colors[SWAP] = A_BOLD; CRT_colors[SWAP] = A_BOLD;
@ -257,6 +262,10 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CHECK_BOX] = A_BOLD; CRT_colors[CHECK_BOX] = A_BOLD;
CRT_colors[CHECK_MARK] = A_NORMAL; CRT_colors[CHECK_MARK] = A_NORMAL;
CRT_colors[CHECK_TEXT] = A_NORMAL; CRT_colors[CHECK_TEXT] = A_NORMAL;
CRT_colors[CPU_IOWAIT] = A_NORMAL;
CRT_colors[CPU_IRQ] = A_BOLD;
CRT_colors[CPU_SOFTIRQ] = A_BOLD;
CRT_colors[HOSTNAME] = A_BOLD;
} else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE) { } else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE) {
CRT_colors[RESET_COLOR] = ColorPair(Black,White); CRT_colors[RESET_COLOR] = ColorPair(Black,White);
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,White); CRT_colors[DEFAULT_COLOR] = ColorPair(Black,White);
@ -268,6 +277,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Yellow,White); CRT_colors[UPTIME] = ColorPair(Yellow,White);
CRT_colors[BATTERY] = ColorPair(Yellow,White);
CRT_colors[LARGE_NUMBER] = ColorPair(Red,White); CRT_colors[LARGE_NUMBER] = ColorPair(Red,White);
CRT_colors[METER_TEXT] = ColorPair(Blue,White); CRT_colors[METER_TEXT] = ColorPair(Blue,White);
CRT_colors[METER_VALUE] = ColorPair(Black,White); CRT_colors[METER_VALUE] = ColorPair(Black,White);
@ -277,11 +287,13 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_SHADOW] = A_BOLD | ColorPair(Black,White); CRT_colors[PROCESS_SHADOW] = A_BOLD | ColorPair(Black,White);
CRT_colors[PROCESS_TAG] = ColorPair(White,Blue); CRT_colors[PROCESS_TAG] = ColorPair(White,Blue);
CRT_colors[PROCESS_MEGABYTES] = ColorPair(Blue,White); CRT_colors[PROCESS_MEGABYTES] = ColorPair(Blue,White);
CRT_colors[PROCESS_BASENAME] = ColorPair(Green,White); CRT_colors[PROCESS_BASENAME] = ColorPair(Blue,White);
CRT_colors[PROCESS_TREE] = ColorPair(Blue,White); CRT_colors[PROCESS_TREE] = ColorPair(Green,White);
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,White); CRT_colors[PROCESS_R_STATE] = ColorPair(Green,White);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White); CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White);
CRT_colors[PROCESS_LOW_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_BORDER] = ColorPair(Blue,White);
CRT_colors[BAR_SHADOW] = ColorPair(Black,White); CRT_colors[BAR_SHADOW] = ColorPair(Black,White);
CRT_colors[SWAP] = ColorPair(Red,White); CRT_colors[SWAP] = ColorPair(Red,White);
@ -305,10 +317,14 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CPU_NICE] = ColorPair(Cyan,White); CRT_colors[CPU_NICE] = ColorPair(Cyan,White);
CRT_colors[CPU_NORMAL] = ColorPair(Green,White); CRT_colors[CPU_NORMAL] = ColorPair(Green,White);
CRT_colors[CPU_KERNEL] = ColorPair(Red,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_BOX] = ColorPair(Blue,White);
CRT_colors[CHECK_MARK] = ColorPair(Black,White); CRT_colors[CHECK_MARK] = ColorPair(Black,White);
CRT_colors[CHECK_TEXT] = ColorPair(Black,White); CRT_colors[CHECK_TEXT] = ColorPair(Black,White);
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black);
CRT_colors[CPU_IRQ] = ColorPair(Blue,White);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,White);
CRT_colors[HOSTNAME] = ColorPair(Black,White);
} else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE2) { } else if (CRT_colorScheme == COLORSCHEME_BLACKONWHITE2) {
CRT_colors[RESET_COLOR] = ColorPair(Black,Black); CRT_colors[RESET_COLOR] = ColorPair(Black,Black);
CRT_colors[DEFAULT_COLOR] = ColorPair(Black,Black); CRT_colors[DEFAULT_COLOR] = ColorPair(Black,Black);
@ -320,6 +336,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,Black); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Blue,Black);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Yellow,Black); CRT_colors[UPTIME] = ColorPair(Yellow,Black);
CRT_colors[BATTERY] = ColorPair(Yellow,Black);
CRT_colors[LARGE_NUMBER] = ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Blue,Black); CRT_colors[METER_TEXT] = ColorPair(Blue,Black);
CRT_colors[METER_VALUE] = ColorPair(Black,Black); CRT_colors[METER_VALUE] = ColorPair(Black,Black);
@ -334,6 +351,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black); CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black); CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_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_BORDER] = ColorPair(Blue,Black);
CRT_colors[BAR_SHADOW] = ColorPair(Black,Black); CRT_colors[BAR_SHADOW] = ColorPair(Black,Black);
CRT_colors[SWAP] = ColorPair(Red,Black); CRT_colors[SWAP] = ColorPair(Red,Black);
@ -361,6 +380,10 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CHECK_BOX] = ColorPair(Blue,Black); CRT_colors[CHECK_BOX] = ColorPair(Blue,Black);
CRT_colors[CHECK_MARK] = ColorPair(Black,Black); CRT_colors[CHECK_MARK] = ColorPair(Black,Black);
CRT_colors[CHECK_TEXT] = ColorPair(Black,Black); CRT_colors[CHECK_TEXT] = ColorPair(Black,Black);
CRT_colors[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[HOSTNAME] = ColorPair(White,Black);
} else if (CRT_colorScheme == COLORSCHEME_MIDNIGHT) { } else if (CRT_colorScheme == COLORSCHEME_MIDNIGHT) {
CRT_colors[RESET_COLOR] = ColorPair(White,Blue); CRT_colors[RESET_COLOR] = ColorPair(White,Blue);
CRT_colors[DEFAULT_COLOR] = ColorPair(White,Blue); CRT_colors[DEFAULT_COLOR] = ColorPair(White,Blue);
@ -372,6 +395,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[UPTIME] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[BATTERY] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Blue); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Blue);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Blue); CRT_colors[METER_TEXT] = ColorPair(Cyan,Blue);
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Blue); CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Blue);
@ -386,6 +410,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Blue); CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Blue);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue); CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue);
CRT_colors[PROCESS_LOW_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_BORDER] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[BAR_SHADOW] = ColorPair(Cyan,Blue); CRT_colors[BAR_SHADOW] = ColorPair(Cyan,Blue);
CRT_colors[SWAP] = ColorPair(Red,Blue); CRT_colors[SWAP] = ColorPair(Red,Blue);
@ -413,6 +439,10 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CHECK_BOX] = ColorPair(Cyan,Blue); CRT_colors[CHECK_BOX] = ColorPair(Cyan,Blue);
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(White,Blue); CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(White,Blue);
CRT_colors[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue); CRT_colors[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue);
CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,Blue);
CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Black,Blue);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Black,Blue);
CRT_colors[HOSTNAME] = ColorPair(White,Blue);
} else if (CRT_colorScheme == COLORSCHEME_BLACKNIGHT) { } else if (CRT_colorScheme == COLORSCHEME_BLACKNIGHT) {
CRT_colors[RESET_COLOR] = ColorPair(Cyan,Black); CRT_colors[RESET_COLOR] = ColorPair(Cyan,Black);
CRT_colors[DEFAULT_COLOR] = ColorPair(Cyan,Black); CRT_colors[DEFAULT_COLOR] = ColorPair(Cyan,Black);
@ -424,6 +454,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = ColorPair(Green,Black); CRT_colors[UPTIME] = ColorPair(Green,Black);
CRT_colors[BATTERY] = ColorPair(Green,Black);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Black); CRT_colors[METER_TEXT] = ColorPair(Cyan,Black);
CRT_colors[METER_VALUE] = ColorPair(Green,Black); CRT_colors[METER_VALUE] = ColorPair(Green,Black);
@ -435,6 +466,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green,Black); CRT_colors[PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green,Black);
CRT_colors[PROCESS_BASENAME] = A_BOLD | ColorPair(Green,Black); CRT_colors[PROCESS_BASENAME] = A_BOLD | ColorPair(Green,Black);
CRT_colors[PROCESS_TREE] = ColorPair(Cyan,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_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black); CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black); CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
@ -461,10 +494,14 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CPU_NICE] = ColorPair(Blue,Black); CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black); CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,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_BOX] = ColorPair(Green,Black);
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,Black); CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,Black);
CRT_colors[CHECK_TEXT] = ColorPair(Cyan,Black); CRT_colors[CHECK_TEXT] = ColorPair(Cyan,Black);
CRT_colors[CPU_IOWAIT] = ColorPair(Yellow,Black);
CRT_colors[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Blue,Black);
CRT_colors[HOSTNAME] = ColorPair(Green,Black);
} else { } else {
/* Default */ /* Default */
CRT_colors[RESET_COLOR] = ColorPair(White,Black); CRT_colors[RESET_COLOR] = ColorPair(White,Black);
@ -477,6 +514,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White); CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = ColorPair(Black,White);
CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan); CRT_colors[FAILED_SEARCH] = ColorPair(Red,Cyan);
CRT_colors[UPTIME] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[UPTIME] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[BATTERY] = A_BOLD | ColorPair(Cyan,Black);
CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black); CRT_colors[LARGE_NUMBER] = A_BOLD | ColorPair(Red,Black);
CRT_colors[METER_TEXT] = ColorPair(Cyan,Black); CRT_colors[METER_TEXT] = ColorPair(Cyan,Black);
CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Black); CRT_colors[METER_VALUE] = A_BOLD | ColorPair(Cyan,Black);
@ -491,6 +529,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black); CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black); CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_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_BORDER] = A_BOLD;
CRT_colors[BAR_SHADOW] = A_BOLD | ColorPair(Black,Black); CRT_colors[BAR_SHADOW] = A_BOLD | ColorPair(Black,Black);
CRT_colors[SWAP] = ColorPair(Red,Black); CRT_colors[SWAP] = ColorPair(Red,Black);
@ -518,5 +558,9 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CHECK_BOX] = ColorPair(Cyan,Black); CRT_colors[CHECK_BOX] = ColorPair(Cyan,Black);
CRT_colors[CHECK_MARK] = A_BOLD; CRT_colors[CHECK_MARK] = A_BOLD;
CRT_colors[CHECK_TEXT] = A_NORMAL; CRT_colors[CHECK_TEXT] = A_NORMAL;
CRT_colors[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black);
CRT_colors[CPU_IRQ] = ColorPair(Yellow,Black);
CRT_colors[CPU_SOFTIRQ] = ColorPair(Magenta,Black);
CRT_colors[HOSTNAME] = A_BOLD;
} }
} }

42
CRT.h
View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CRT #ifndef HEADER_CRT
#define HEADER_CRT #define HEADER_CRT
@ -17,8 +17,11 @@ in the source distribution for its full text.
#include "String.h" #include "String.h"
#include "config.h"
#include "debug.h" #include "debug.h"
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
#define COLORSCHEME_DEFAULT 0 #define COLORSCHEME_DEFAULT 0
#define COLORSCHEME_MONOCHROME 1 #define COLORSCHEME_MONOCHROME 1
#define COLORSCHEME_BLACKONWHITE 2 #define COLORSCHEME_BLACKONWHITE 2
@ -26,6 +29,15 @@ in the source distribution for its full text.
#define COLORSCHEME_MIDNIGHT 4 #define COLORSCHEME_MIDNIGHT 4
#define COLORSCHEME_BLACKNIGHT 5 #define COLORSCHEME_BLACKNIGHT 5
#define Black COLOR_BLACK
#define Red COLOR_RED
#define Green COLOR_GREEN
#define Yellow COLOR_YELLOW
#define Blue COLOR_BLUE
#define Magenta COLOR_MAGENTA
#define Cyan COLOR_CYAN
#define White COLOR_WHITE
//#link curses //#link curses
bool CRT_hasColors; bool CRT_hasColors;
@ -46,6 +58,7 @@ typedef enum ColorElements_ {
METER_VALUE, METER_VALUE,
LED_COLOR, LED_COLOR,
UPTIME, UPTIME,
BATTERY,
TASKS_TOTAL, TASKS_TOTAL,
TASKS_RUNNING, TASKS_RUNNING,
SWAP, SWAP,
@ -58,6 +71,8 @@ typedef enum ColorElements_ {
PROCESS_BASENAME, PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY, PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY, PROCESS_LOW_PRIORITY,
PROCESS_THREAD,
PROCESS_THREAD_BASENAME,
BAR_BORDER, BAR_BORDER,
BAR_SHADOW, BAR_SHADOW,
GRAPH_1, GRAPH_1,
@ -84,29 +99,36 @@ typedef enum ColorElements_ {
CPU_NORMAL, CPU_NORMAL,
CPU_KERNEL, CPU_KERNEL,
HELP_BOLD, HELP_BOLD,
CPU_IOWAIT,
CPU_IRQ,
CPU_SOFTIRQ,
HOSTNAME,
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
extern int CRT_colors[LAST_COLORELEMENT];
extern int CRT_colorScheme; // TODO: centralize these in Settings.
extern int CRT_delay; extern int CRT_delay;
void CRT_init(); extern int CRT_colorScheme;
extern int CRT_colors[LAST_COLORELEMENT];
char* CRT_termType;
// TODO: pass an instance of Settings instead.
void CRT_init(int delay, int colorScheme);
void CRT_done(); void CRT_done();
int CRT_readKey(); int CRT_readKey();
void CRT_handleSIGSEGV(int signal); void CRT_disableDelay();
void CRT_handleSIGTERM(int signal);
void CRT_setColors(int colorScheme);
void CRT_enableDelay(); void CRT_enableDelay();
void CRT_disableDelay(); void CRT_setColors(int colorScheme);
#endif #endif

View File

@ -1,134 +0,0 @@
#include "CategoriesListBox.h"
#include "AvailableMetersListBox.h"
#include "MetersListBox.h"
#include "DisplayOptionsListBox.h"
#include "ColumnsListBox.h"
#include "ColorsListBox.h"
#include "AvailableColumnsListBox.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct CategoriesListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
} CategoriesListBox;
}*/
/* private property */
char* MetersFunctions[10] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
/* private property */
char* AvailableMetersFunctions[10] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done "};
/* private property */
char* DisplayOptionsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
/* private property */
char* ColumnsFunctions[10] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
/* private property */
char* ColorsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
/* private property */
char* AvailableColumnsFunctions[10] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done "};
CategoriesListBox* CategoriesListBox_new(Settings* settings, ScreenManager* scr) {
CategoriesListBox* this = (CategoriesListBox*) malloc(sizeof(CategoriesListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = CategoriesListBox_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = CategoriesListBox_eventHandler;
ListBox_setHeader(super, "Setup");
ListBox_add(super, (Object*) ListItem_new("Meters", 0));
ListBox_add(super, (Object*) ListItem_new("Display options", 0));
ListBox_add(super, (Object*) ListItem_new("Colors", 0));
ListBox_add(super, (Object*) ListItem_new("Columns", 0));
return this;
}
void CategoriesListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
CategoriesListBox* this = (CategoriesListBox*) object;
ListBox_done(super);
free(this);
}
HandlerResult CategoriesListBox_eventHandler(ListBox* super, int ch) {
CategoriesListBox* this = (CategoriesListBox*) super;
HandlerResult result = IGNORED;
int previous = ListBox_getSelectedIndex(super);
switch (ch) {
case KEY_UP:
case KEY_DOWN:
case KEY_NPAGE:
case KEY_PPAGE:
case KEY_HOME:
case KEY_END: {
ListBox_onKey(super, ch);
int selected = ListBox_getSelectedIndex(super);
if (previous != selected) {
int size = ScreenManager_size(this->scr);
for (int i = 1; i < size; i++)
ScreenManager_remove(this->scr, 1);
switch (selected) {
case 0:
CategoriesListBox_makeMetersPage(this);
break;
case 1:
CategoriesListBox_makeDisplayOptionsPage(this);
break;
case 2:
CategoriesListBox_makeColorsPage(this);
break;
case 3:
CategoriesListBox_makeColumnsPage(this);
break;
}
}
result = HANDLED;
}
}
return result;
}
void CategoriesListBox_makeMetersPage(CategoriesListBox* this) {
ListBox* lbLeftMeters = (ListBox*) MetersListBox_new(this->settings, "Left column", this->settings->header->leftMeters, this->scr);
ListBox* lbRightMeters = (ListBox*) MetersListBox_new(this->settings, "Right column", this->settings->header->rightMeters, this->scr);
ListBox* lbAvailableMeters = (ListBox*) AvailableMetersListBox_new(this->settings, lbLeftMeters, lbRightMeters, this->scr);
ScreenManager_add(this->scr, lbLeftMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, lbRightMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, lbAvailableMeters, FunctionBar_new(10, AvailableMetersFunctions, NULL, NULL), -1);
}
void CategoriesListBox_makeDisplayOptionsPage(CategoriesListBox* this) {
ListBox* lbDisplayOptions = (ListBox*) DisplayOptionsListBox_new(this->settings, this->scr);
ScreenManager_add(this->scr, lbDisplayOptions, FunctionBar_new(10, DisplayOptionsFunctions, NULL, NULL), -1);
}
void CategoriesListBox_makeColorsPage(CategoriesListBox* this) {
ListBox* lbColors = (ListBox*) ColorsListBox_new(this->settings, this->scr);
ScreenManager_add(this->scr, lbColors, FunctionBar_new(10, ColorsFunctions, NULL, NULL), -1);
}
void CategoriesListBox_makeColumnsPage(CategoriesListBox* this) {
ListBox* lbColumns = (ListBox*) ColumnsListBox_new(this->settings, this->scr);
ListBox* lbAvailableColumns = (ListBox*) AvailableColumnsListBox_new(this->settings, lbColumns, this->scr);
ScreenManager_add(this->scr, lbColumns, FunctionBar_new(10, ColumnsFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, lbAvailableColumns, FunctionBar_new(10, AvailableColumnsFunctions, NULL, NULL), -1);
}

View File

@ -1,40 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_CategoriesListBox
#define HEADER_CategoriesListBox
#include "AvailableMetersListBox.h"
#include "MetersListBox.h"
#include "DisplayOptionsListBox.h"
#include "ListBox.h"
#include "debug.h"
#include <assert.h>
typedef struct CategoriesListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
} CategoriesListBox;
CategoriesListBox* CategoriesListBox_new(Settings* settings, ScreenManager* scr);
void CategoriesListBox_delete(Object* object);
HandlerResult CategoriesListBox_eventHandler(ListBox* super, int ch);
void CategoriesListBox_makeMetersPage(CategoriesListBox* this);
void CategoriesListBox_makeDisplayOptionsPage(CategoriesListBox* this);
void CategoriesListBox_makeColorsPage(CategoriesListBox* this);
void CategoriesListBox_makeColumnsPage(CategoriesListBox* this);
#endif

134
CategoriesPanel.c Normal file
View File

@ -0,0 +1,134 @@
#include "CategoriesPanel.h"
#include "AvailableMetersPanel.h"
#include "MetersPanel.h"
#include "DisplayOptionsPanel.h"
#include "ColumnsPanel.h"
#include "ColorsPanel.h"
#include "AvailableColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct CategoriesPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} CategoriesPanel;
}*/
static char* MetersFunctions[] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
static char* AvailableMetersFunctions[] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done ", NULL};
static char* DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
static char* ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
static char* ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
static char* AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL};
static void CategoriesPanel_delete(Object* object) {
Panel* super = (Panel*) object;
CategoriesPanel* this = (CategoriesPanel*) object;
Panel_done(super);
free(this);
}
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 selected = Panel_getSelectedIndex(super);
switch (ch) {
case EVENT_SETSELECTED:
result = HANDLED;
break;
case KEY_UP:
case KEY_DOWN:
case KEY_NPAGE:
case KEY_PPAGE:
case KEY_HOME:
case KEY_END: {
int previous = selected;
Panel_onKey(super, ch);
selected = Panel_getSelectedIndex(super);
if (previous != selected)
result = HANDLED;
break;
}
}
if (result == HANDLED) {
int size = ScreenManager_size(this->scr);
for (int i = 1; i < size; i++)
ScreenManager_remove(this->scr, 1);
switch (selected) {
case 0:
CategoriesPanel_makeMetersPage(this);
break;
case 1:
CategoriesPanel_makeDisplayOptionsPage(this);
break;
case 2:
CategoriesPanel_makeColorsPage(this);
break;
case 3:
CategoriesPanel_makeColumnsPage(this);
break;
}
}
return result;
}
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;
}

31
CategoriesPanel.h Normal file
View File

@ -0,0 +1,31 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CategoriesPanel
#define HEADER_CategoriesPanel
#include "AvailableMetersPanel.h"
#include "MetersPanel.h"
#include "DisplayOptionsPanel.h"
#include "ColumnsPanel.h"
#include "ColorsPanel.h"
#include "AvailableColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
typedef struct CategoriesPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} CategoriesPanel;
void CategoriesPanel_makeMetersPage(CategoriesPanel* this);
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr);
#endif

132
ChangeLog
View File

@ -1,4 +1,134 @@
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
(thanks to Bert Wesarg)
* BUGFIX: Fix use of configurable /proc location
(thanks to Florent Thoumie)
* Fix memory percentage calculation and make it saner
(thanks to Olev Kartau for the report)
* Added display of DRS, DT, LRS and TRS
(thanks to Matthias Lederhofer)
* BUGFIX: LRS and DRS memory values were flipped
(thanks to Matthias Lederhofer)
* BUGFIX: Don't crash on very high UIDs
(thanks to Egmont Koblinger)
What's new in version 0.6.5
* Add hardened-debug flags for debugging with Hardened GCC
* BUGFIX: Handle error condition when a directory vanishes
from /proc
* BUGFIX: Fix leak of process command line
* BUGFIX: Collect orphaned items when arranging the tree view.
(thanks to Wolfram Schlich for assistance with debugging)
* Separate proc and memory debugging into separate #defines.
* BUGFIX: Fix message when configure fails due to
missing libraries
(thanks to Jon)
* BUGFIX: Don't truncate value when displaying a very large
process
(thanks to Bo Liu)
What's new in version 0.6.4
* Add an option to split the display of kernel time
in the CPU meter into system, IO-wait, IRQ and soft-IRQ.
(thanks to Philipp Richter)
* --sort-key flag in the command-line, overriding the
saved setting in .htoprc for the session.
(thanks to Rodolfo Borges)
* BUGFIX: Fixed string overflow on uptime display.
(thanks to Marc Cahalan)
What's new in version 0.6.3
* Performance improvements: uses much less CPU than the
previous release with the default setup.
* Use 64-bit values when storing processor times to
avoid overflow.
* Memory consumption improvements, compensating storage
of 64-bit values.
* Internal change: rename TypedVector to Vector and
ListBox (and related classes) to Panel.
* Have configure actually fail when needed libraries or
headers are not found.
* Horizontally scroll in larger increments when on the
Linux console because of slow update of unaccelerated fb
* No longer untag processes after sending a signal
(useful for when SIGTERM fails and one wants to try again
with SIGKILL). All processes can be untagged at once with 'U'.
(thanks to A. Costa for the suggestion)
What's new in version 0.6.2 What's new in version 0.6.2
* BUGFIX: Fixed crash when using some .htoprc files from 0.6 * BUGFIX: Fixed crash when using some .htoprc files from 0.6
@ -137,7 +267,7 @@ What's new in version 0.4
* Clock and load average meters * Clock and load average meters
(thanks to Marc Calahan) (thanks to Marc Calahan)
* BUGFIX: numeric swap indicator was printing bogus value * BUGFIX: numeric swap indicator was printing bogus value
* BUGFIX: internal fixes on ListBox widget * BUGFIX: internal fixes on Panel widget
* Clear the bottom line when exiting * Clear the bottom line when exiting
* Press "F3" during search to walk through the results * Press "F3" during search to walk through the results
* Improved navigation on column configuration screen * Improved navigation on column configuration screen

View File

@ -16,26 +16,19 @@ in the source distribution for its full text.
typedef struct CheckItem_ { typedef struct CheckItem_ {
Object super; Object super;
char* text; char* text;
bool* value; bool value;
bool* ref;
} CheckItem; } CheckItem;
extern char* CHECKITEM_CLASS;
}*/ }*/
/* private property */ #ifdef DEBUG
char* CHECKITEM_CLASS = "CheckItem"; char* CHECKITEM_CLASS = "CheckItem";
#else
#define CHECKITEM_CLASS NULL
#endif
CheckItem* CheckItem_new(char* text, bool* value) { static void CheckItem_delete(Object* cast) {
CheckItem* this = malloc(sizeof(CheckItem));
((Object*)this)->class = 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) {
CheckItem* this = (CheckItem*)cast; CheckItem* this = (CheckItem*)cast;
assert (this != NULL); assert (this != NULL);
@ -43,14 +36,39 @@ void CheckItem_delete(Object* cast) {
free(this); free(this);
} }
void CheckItem_display(Object* cast, RichString* out) { static void CheckItem_display(Object* cast, RichString* out) {
CheckItem* this = (CheckItem*)cast; CheckItem* this = (CheckItem*)cast;
assert (this != NULL); assert (this != NULL);
RichString_write(out, CRT_colors[CHECK_BOX], "["); RichString_write(out, CRT_colors[CHECK_BOX], "[");
if (*(this->value)) if (CheckItem_get(this))
RichString_append(out, CRT_colors[CHECK_MARK], "x"); RichString_append(out, CRT_colors[CHECK_MARK], "x");
else else
RichString_append(out, CRT_colors[CHECK_MARK], " "); RichString_append(out, CRT_colors[CHECK_MARK], " ");
RichString_append(out, CRT_colors[CHECK_BOX], "] "); RichString_append(out, CRT_colors[CHECK_BOX], "] ");
RichString_append(out, CRT_colors[CHECK_TEXT], this->text); RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
} }
CheckItem* CheckItem_new(char* text, bool* ref, 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;
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;
}

View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CheckItem #ifndef HEADER_CheckItem
#define HEADER_CheckItem #define HEADER_CheckItem
@ -18,16 +18,21 @@ in the source distribution for its full text.
typedef struct CheckItem_ { typedef struct CheckItem_ {
Object super; Object super;
char* text; char* text;
bool* value; bool value;
bool* ref;
} CheckItem; } CheckItem;
#ifdef DEBUG
extern char* CHECKITEM_CLASS; extern char* CHECKITEM_CLASS;
#else
#define CHECKITEM_CLASS NULL
#endif
CheckItem* CheckItem_new(char* text, bool* ref, bool value);
CheckItem* CheckItem_new(char* text, bool* value); void CheckItem_set(CheckItem* this, bool value);
void CheckItem_delete(Object* cast); bool CheckItem_get(CheckItem* this);
void CheckItem_display(Object* cast, RichString* out);
#endif #endif

View File

@ -12,10 +12,17 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
/* private */ int ClockMeter_attributes[] = {
static int ClockMeter_attributes[] = { CLOCK }; CLOCK
};
static 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);
}
/* private */
MeterType ClockMeter = { MeterType ClockMeter = {
.setValues = ClockMeter_setValues, .setValues = ClockMeter_setValues,
.display = NULL, .display = NULL,
@ -27,10 +34,3 @@ MeterType ClockMeter = {
.uiName = "Clock", .uiName = "Clock",
.caption = "Time: ", .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);
}

View File

@ -15,7 +15,8 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
extern int ClockMeter_attributes[];
void ClockMeter_setValues(Meter* this, char* buffer, int size); extern MeterType ClockMeter;
#endif #endif

View File

@ -1,99 +0,0 @@
#include "CRT.h"
#include "ColorsListBox.h"
#include "ListBox.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsListBox.h
// * Add the entry in the ColorSchemes array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
/*{
typedef struct ColorsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
bool check[5];
} ColorsListBox;
}*/
/* private */
static char* ColorSchemes[] = {
"Default",
"Monochromatic",
"Black on White",
"Light Terminal",
"MC",
"Black Night",
NULL
};
ColorsListBox* ColorsListBox_new(Settings* settings, ScreenManager* scr) {
ColorsListBox* this = (ColorsListBox*) malloc(sizeof(ColorsListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = ColorsListBox_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = ColorsListBox_EventHandler;
ListBox_setHeader(super, "Colors");
for (int i = 0; ColorSchemes[i] != NULL; i++) {
ListBox_add(super, (Object*) CheckItem_new(String_copy(ColorSchemes[i]), &(this->check[i])));
this->check[i] = false;
}
this->check[settings->colorScheme] = true;
return this;
}
void ColorsListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
ColorsListBox* this = (ColorsListBox*) object;
ListBox_done(super);
free(this);
}
HandlerResult ColorsListBox_EventHandler(ListBox* super, int ch) {
ColorsListBox* this = (ColorsListBox*) super;
HandlerResult result = IGNORED;
int mark = ListBox_getSelectedIndex(super);
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case ' ':
for (int i = 0; ColorSchemes[i] != NULL; i++) {
this->check[i] = false;
}
this->check[mark] = true;
this->settings->colorScheme = mark;
result = HANDLED;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
CRT_setColors(mark);
ListBox* lbMenu = (ListBox*) TypedVector_get(this->scr->items, 0);
Header_draw(header);
RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]);
RichString_setAttr(&(lbMenu->header), CRT_colors[PANEL_HEADER_UNFOCUS]);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}

View File

@ -1,32 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_ColorsListBox
#define HEADER_ColorsListBox
#include "ListBox.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct ColorsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
bool check[5];
} ColorsListBox;
ColorsListBox* ColorsListBox_new(Settings* settings, ScreenManager* scr);
void ColorsListBox_delete(Object* object);
HandlerResult ColorsListBox_EventHandler(ListBox* super, int ch);
#endif

95
ColorsPanel.c Normal file
View File

@ -0,0 +1,95 @@
#include "CRT.h"
#include "ColorsPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h
// * Add the entry in the ColorSchemes array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
/*{
typedef struct ColorsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColorsPanel;
}*/
static char* ColorSchemes[] = {
"Default",
"Monochromatic",
"Black on White",
"Light Terminal",
"MC",
"Black Night",
NULL
};
static void ColorsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
ColorsPanel* this = (ColorsPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
ColorsPanel* this = (ColorsPanel*) super;
HandlerResult result = IGNORED;
int mark = Panel_getSelectedIndex(super);
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case ' ':
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;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
CRT_setColors(mark);
Panel* menu = (Panel*) Vector_get(this->scr->items, 0);
Header_draw(header);
RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]);
RichString_setAttr(&(menu->header), CRT_colors[PANEL_HEADER_UNFOCUS]);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}
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]), NULL, false));
}
CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true);
return this;
}

33
ColorsPanel.h Normal file
View File

@ -0,0 +1,33 @@
/* Do not edit this file. It was automatically generated. */
#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>
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h
// * Add the entry in the ColorSchemes array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
typedef struct ColorsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColorsPanel;
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr);
#endif

View File

@ -1,104 +0,0 @@
#include "ColumnsListBox.h"
#include "ListBox.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct ColumnsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
} ColumnsListBox;
}*/
ColumnsListBox* ColumnsListBox_new(Settings* settings, ScreenManager* scr) {
ColumnsListBox* this = (ColumnsListBox*) malloc(sizeof(ColumnsListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = ColumnsListBox_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = ColumnsListBox_eventHandler;
ListBox_setHeader(super, "Active Columns");
ProcessField* fields = this->settings->pl->fields;
for (; *fields; fields++) {
ListBox_add(super, (Object*) ListItem_new(Process_fieldNames[*fields], 0));
}
return this;
}
void ColumnsListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
ColumnsListBox* this = (ColumnsListBox*) object;
ListBox_done(super);
free(this);
}
void ColumnsListBox_update(ListBox* super) {
ColumnsListBox* this = (ColumnsListBox*) super;
int size = ListBox_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*) ListBox_get(super, i))->value;
for (int j = 1; j <= LAST_PROCESSFIELD; j++) {
if (String_eq(text, Process_fieldNames[j])) {
this->settings->pl->fields[i] = j;
break;
}
}
}
this->settings->pl->fields[size] = 0;
}
HandlerResult ColumnsListBox_eventHandler(ListBox* super, int ch) {
int selected = ListBox_getSelectedIndex(super);
HandlerResult result = IGNORED;
int size = ListBox_getSize(super);
switch(ch) {
case KEY_F(7):
case '[':
case '-':
{
if (selected < size - 1)
ListBox_moveSelectedUp(super);
result = HANDLED;
break;
}
case KEY_F(8):
case ']':
case '+':
{
if (selected < size - 2)
ListBox_moveSelectedDown(super);
result = HANDLED;
break;
}
case KEY_F(9):
case KEY_DC:
{
if (selected < size - 1) {
ListBox_remove(super, selected);
}
result = HANDLED;
break;
}
}
if (result == HANDLED)
ColumnsListBox_update(super);
return result;
}

View File

@ -1,32 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_ColumnsListBox
#define HEADER_ColumnsListBox
#include "ListBox.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct ColumnsListBox_ {
ListBox super;
Settings* settings;
TypedVector* columns;
ScreenManager* scr;
} ColumnsListBox;
ColumnsListBox* ColumnsListBox_new(Settings* settings, ScreenManager* scr);
void ColumnsListBox_delete(Object* object);
void ColumnsListBox_update(ListBox* super);
HandlerResult ColumnsListBox_eventHandler(ListBox* super, int ch);
#endif

111
ColumnsPanel.c Normal file
View File

@ -0,0 +1,111 @@
#include "ColumnsPanel.h"
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct ColumnsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColumnsPanel;
}*/
static void ColumnsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
ColumnsPanel* this = (ColumnsPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
int selected = Panel_getSelectedIndex(super);
HandlerResult result = IGNORED;
int size = Panel_size(super);
switch(ch) {
case KEY_F(7):
case '[':
case '-':
{
if (selected < size - 1)
Panel_moveSelectedUp(super);
result = HANDLED;
break;
}
case KEY_F(8):
case ']':
case '+':
{
if (selected < size - 2)
Panel_moveSelectedDown(super);
result = HANDLED;
break;
}
case KEY_F(9):
case KEY_DC:
{
if (selected < size - 1) {
Panel_remove(super, selected);
}
result = HANDLED;
break;
}
}
if (result == HANDLED)
ColumnsPanel_update(super);
return result;
}
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;
}
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));
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;
}

30
ColumnsPanel.h Normal file
View File

@ -0,0 +1,30 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ColumnsPanel
#define HEADER_ColumnsPanel
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct ColumnsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColumnsPanel;
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr);
int ColumnsPanel_fieldNameToIndex(const char* name);
void ColumnsPanel_update(Panel* super);
#endif

View File

@ -1,25 +1,25 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include "DebugMemory.h"
#undef strdup #undef strdup
#undef malloc #undef malloc
#undef realloc #undef realloc
#undef calloc #undef calloc
#undef free #undef free
#include "DebugMemory.h"
/*{ /*{
typedef struct DebugMemoryItem_ DebugMemoryItem; typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ { struct DebugMemoryItem_ {
int magic;
void* data; void* data;
char* file; char* file;
int line; int line;
@ -31,12 +31,15 @@ typedef struct DebugMemory_ {
int allocations; int allocations;
int deallocations; int deallocations;
int size; int size;
bool totals;
FILE* file; FILE* file;
} DebugMemory; } DebugMemory;
}*/ }*/
/* private property */ #if defined(DEBUG)
DebugMemory* singleton = NULL;
static DebugMemory* singleton = NULL;
void DebugMemory_new() { void DebugMemory_new() {
if (singleton) if (singleton)
@ -46,41 +49,65 @@ void DebugMemory_new() {
singleton->allocations = 0; singleton->allocations = 0;
singleton->deallocations = 0; singleton->deallocations = 0;
singleton->size = 0; singleton->size = 0;
#ifdef DEBUG_ALLOC
singleton->file = fopen("/tmp/htop-debug-alloc.txt", "w"); 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) { void* DebugMemory_malloc(int size, char* file, int line, char* str) {
void* data = malloc(size); void* data = malloc(size);
DebugMemory_registerAllocation(data, file, line); DebugMemory_registerAllocation(data, file, line);
fprintf(singleton->file, "%d\t%s:%d\n", size, 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; return data;
} }
void* DebugMemory_calloc(int a, int b, char* file, int line) { void* DebugMemory_calloc(int a, int b, char* file, int line) {
void* data = calloc(a, b); void* data = calloc(a, b);
DebugMemory_registerAllocation(data, file, line); 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); fprintf(singleton->file, "%d\t%s:%d\n", a*b, file, line);
}
return data; return data;
} }
void* DebugMemory_realloc(void* ptr, int size, char* file, int line) { void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str) {
if (ptr != NULL) if (ptr != NULL)
DebugMemory_registerDeallocation(ptr, file, line); DebugMemory_registerDeallocation(ptr, file, line);
void* data = realloc(ptr, size); void* data = realloc(ptr, size);
DebugMemory_registerAllocation(data, file, line); DebugMemory_registerAllocation(data, file, line);
fprintf(singleton->file, "%d\t%s:%d\n", size, 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; return data;
} }
void* DebugMemory_strdup(char* str, char* file, int line) { void* DebugMemory_strdup(char* str, char* file, int line) {
assert(str);
char* data = strdup(str); char* data = strdup(str);
DebugMemory_registerAllocation(data, file, line); 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); fprintf(singleton->file, "%d\t%s:%d\n", (int) strlen(str), file, line);
}
return data; return data;
} }
void DebugMemory_free(void* data, char* file, int line) { void DebugMemory_free(void* data, char* file, int line) {
assert(data);
DebugMemory_registerDeallocation(data, file, line); 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); free(data);
} }
@ -91,6 +118,7 @@ void DebugMemory_assertSize() {
DebugMemoryItem* walk = singleton->first; DebugMemoryItem* walk = singleton->first;
int i = 0; int i = 0;
while (walk != NULL) { while (walk != NULL) {
assert(walk->magic == 11061980);
i++; i++;
walk = walk->next; walk = walk->next;
} }
@ -104,6 +132,7 @@ int DebugMemory_getBlockCount() {
DebugMemoryItem* walk = singleton->first; DebugMemoryItem* walk = singleton->first;
int i = 0; int i = 0;
while (walk != NULL) { while (walk != NULL) {
assert(walk->magic == 11061980);
i++; i++;
walk = walk->next; walk = walk->next;
} }
@ -115,6 +144,7 @@ void DebugMemory_registerAllocation(void* data, char* file, int line) {
DebugMemory_new(); DebugMemory_new();
DebugMemory_assertSize(); DebugMemory_assertSize();
DebugMemoryItem* item = (DebugMemoryItem*) malloc(sizeof(DebugMemoryItem)); DebugMemoryItem* item = (DebugMemoryItem*) malloc(sizeof(DebugMemoryItem));
item->magic = 11061980;
item->data = data; item->data = data;
item->file = file; item->file = file;
item->line = line; item->line = line;
@ -130,6 +160,7 @@ void DebugMemory_registerAllocation(void* data, char* file, int line) {
walk->next = item; walk->next = item;
break; break;
} }
assert(walk->magic == 11061980);
walk = walk->next; walk = walk->next;
} }
} }
@ -141,14 +172,13 @@ void DebugMemory_registerAllocation(void* data, char* file, int line) {
} }
void DebugMemory_registerDeallocation(void* data, char* file, int line) { void DebugMemory_registerDeallocation(void* data, char* file, int line) {
if (!data)
return;
assert(singleton); assert(singleton);
assert(singleton->first); assert(singleton->first);
DebugMemoryItem* walk = singleton->first; DebugMemoryItem* walk = singleton->first;
DebugMemoryItem* prev = NULL; DebugMemoryItem* prev = NULL;
int val = DebugMemory_getBlockCount(); int val = DebugMemory_getBlockCount();
while (walk != NULL) { while (walk != NULL) {
assert(walk->magic == 11061980);
if (walk->data == data) { if (walk->data == data) {
if (prev == NULL) { if (prev == NULL) {
singleton->first = walk->next; singleton->first = walk->next;
@ -176,6 +206,7 @@ void DebugMemory_report() {
DebugMemoryItem* walk = singleton->first; DebugMemoryItem* walk = singleton->first;
int i = 0; int i = 0;
while (walk != NULL) { while (walk != NULL) {
assert(walk->magic == 11061980);
i++; i++;
fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line); fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line);
walk = walk->next; walk = walk->next;
@ -185,5 +216,12 @@ void DebugMemory_report() {
fprintf(stderr, "%d deallocations\n", singleton->deallocations); fprintf(stderr, "%d deallocations\n", singleton->deallocations);
fprintf(stderr, "%d size\n", singleton->size); fprintf(stderr, "%d size\n", singleton->size);
fprintf(stderr, "%d non-freed blocks\n", i); fprintf(stderr, "%d non-freed blocks\n", i);
if (singleton->file)
fclose(singleton->file); fclose(singleton->file);
} }
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif

View File

@ -1,27 +1,27 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DebugMemory #ifndef HEADER_DebugMemory
#define HEADER_DebugMemory #define HEADER_DebugMemory
#define _GNU_SOURCE #define _GNU_SOURCE
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#undef strdup #undef strdup
#undef malloc #undef malloc
#undef realloc #undef realloc
#undef calloc #undef calloc
#undef free #undef free
typedef struct DebugMemoryItem_ DebugMemoryItem; typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ { struct DebugMemoryItem_ {
int magic;
void* data; void* data;
char* file; char* file;
int line; int line;
@ -33,17 +33,20 @@ typedef struct DebugMemory_ {
int allocations; int allocations;
int deallocations; int deallocations;
int size; int size;
bool totals;
FILE* file; FILE* file;
} DebugMemory; } DebugMemory;
#if defined(DEBUG)
void DebugMemory_new(); void DebugMemory_new();
void* DebugMemory_malloc(int size, char* file, int line); void* DebugMemory_malloc(int size, char* file, int line, char* str);
void* DebugMemory_calloc(int a, int b, char* file, int line); void* DebugMemory_calloc(int a, int b, char* file, int line);
void* DebugMemory_realloc(void* ptr, int size, 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_strdup(char* str, char* file, int line);
@ -59,4 +62,10 @@ void DebugMemory_registerDeallocation(void* data, char* file, int line);
void DebugMemory_report(); void DebugMemory_report();
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif
#endif #endif

View File

@ -1,75 +0,0 @@
#include "DisplayOptionsListBox.h"
#include "ListBox.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct DisplayOptionsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
} DisplayOptionsListBox;
}*/
DisplayOptionsListBox* DisplayOptionsListBox_new(Settings* settings, ScreenManager* scr) {
DisplayOptionsListBox* this = (DisplayOptionsListBox*) malloc(sizeof(DisplayOptionsListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = DisplayOptionsListBox_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = DisplayOptionsListBox_EventHandler;
ListBox_setHeader(super, "Display options");
ListBox_add(super, (Object*) CheckItem_new(String_copy("Tree view"), &(settings->pl->treeView)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes)));
ListBox_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin)));
return this;
}
void DisplayOptionsListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
DisplayOptionsListBox* this = (DisplayOptionsListBox*) object;
ListBox_done(super);
free(this);
}
HandlerResult DisplayOptionsListBox_EventHandler(ListBox* super, int ch) {
DisplayOptionsListBox* this = (DisplayOptionsListBox*) super;
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) ListBox_getSelected(super);
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case ' ':
*(selected->value) = ! *(selected->value);
result = HANDLED;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
Header_calculateHeight(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}

View File

@ -1,31 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_DisplayOptionsListBox
#define HEADER_DisplayOptionsListBox
#include "ListBox.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct DisplayOptionsListBox_ {
ListBox super;
Settings* settings;
ScreenManager* scr;
} DisplayOptionsListBox;
DisplayOptionsListBox* DisplayOptionsListBox_new(Settings* settings, ScreenManager* scr);
void DisplayOptionsListBox_delete(Object* object);
HandlerResult DisplayOptionsListBox_EventHandler(ListBox* super, int ch);
#endif

77
DisplayOptionsPanel.c Normal file
View File

@ -0,0 +1,77 @@
#include "DisplayOptionsPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct DisplayOptionsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} DisplayOptionsPanel;
}*/
static void DisplayOptionsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
DisplayOptionsPanel* this = (DisplayOptionsPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
DisplayOptionsPanel* this = (DisplayOptionsPanel*) super;
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) Panel_getSelected(super);
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case ' ':
CheckItem_set(selected, ! (CheckItem_get(selected)) );
result = HANDLED;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
Header_calculateHeight(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}
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), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Display threads in a different color"), &(settings->pl->highlightThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ)"), &(settings->pl->detailedCPUTime), false));
return this;
}

26
DisplayOptionsPanel.h Normal file
View File

@ -0,0 +1,26 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DisplayOptionsPanel
#define HEADER_DisplayOptionsPanel
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct DisplayOptionsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} DisplayOptionsPanel;
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr);
#endif

View File

@ -28,44 +28,44 @@ typedef struct FunctionBar_ {
bool staticData; bool staticData;
} FunctionBar; } FunctionBar;
extern char* FUNCTIONBAR_CLASS;
}*/ }*/
/* private property */ #ifdef DEBUG
char* FUNCTIONBAR_CLASS = "FunctionBar"; char* FUNCTIONBAR_CLASS = "FunctionBar";
#else
#define FUNCTIONBAR_CLASS NULL
#endif
/* private property */ static 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"};
/* private property */ static char* FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL};
static char* FunctionBar_FLabels[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
/* private property */ 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)};
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) { FunctionBar* FunctionBar_new(char** functions, char** keys, int* events) {
FunctionBar* this = malloc(sizeof(FunctionBar)); FunctionBar* this = malloc(sizeof(FunctionBar));
((Object*) this)->class = FUNCTIONBAR_CLASS; Object_setClass(this, FUNCTIONBAR_CLASS);
((Object*) this)->delete = FunctionBar_delete; ((Object*) this)->delete = FunctionBar_delete;
this->functions = functions; this->functions = functions;
this->size = size;
if (keys && events) { if (keys && events) {
this->staticData = false; this->staticData = false;
this->functions = malloc(sizeof(char*) * size); this->functions = malloc(sizeof(char*) * 15);
this->keys = malloc(sizeof(char*) * size); this->keys = malloc(sizeof(char*) * 15);
this->events = malloc(sizeof(int) * size); this->events = malloc(sizeof(int) * 15);
for (int i = 0; i < size; i++) { int i = 0;
while (i < 15 && functions[i]) {
this->functions[i] = String_copy(functions[i]); this->functions[i] = String_copy(functions[i]);
this->keys[i] = String_copy(keys[i]); this->keys[i] = String_copy(keys[i]);
this->events[i] = events[i]; this->events[i] = events[i];
i++;
} }
this->size = i;
} else { } else {
this->staticData = true; this->staticData = true;
this->functions = functions ? functions : FunctionBar_FLabels; this->functions = functions ? functions : FunctionBar_FLabels;
this->keys = FunctionBar_FKeys; this->keys = FunctionBar_FKeys;
this->events = FunctionBar_FEvents; this->events = FunctionBar_FEvents;
assert((!functions) || this->size == 10); this->size = 10;
} }
return this; return this;
} }

View File

@ -1,9 +1,9 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_FunctionBar #ifndef HEADER_FunctionBar
#define HEADER_FunctionBar #define HEADER_FunctionBar
/* /*
htop htop - FunctionBar.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -30,16 +30,21 @@ typedef struct FunctionBar_ {
bool staticData; bool staticData;
} FunctionBar; } FunctionBar;
#ifdef DEBUG
extern char* FUNCTIONBAR_CLASS; extern char* FUNCTIONBAR_CLASS;
#else
#define FUNCTIONBAR_CLASS NULL
#endif
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events); FunctionBar* FunctionBar_new(char** functions, char** keys, int* events);
void FunctionBar_delete(Object* this); void FunctionBar_delete(Object* cast);
void FunctionBar_draw(FunctionBar* this, char* buffer);
void FunctionBar_setLabel(FunctionBar* this, int event, char* text); void FunctionBar_setLabel(FunctionBar* this, int event, char* text);
void FunctionBar_draw(FunctionBar* this, char* buffer);
void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr); void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr);
int FunctionBar_synthesizeEvent(FunctionBar* this, int pos); int FunctionBar_synthesizeEvent(FunctionBar* this, int pos);

View File

@ -9,6 +9,7 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h>
#include "debug.h" #include "debug.h"
@ -16,10 +17,9 @@ in the source distribution for its full text.
typedef struct Hashtable_ Hashtable; typedef struct Hashtable_ Hashtable;
typedef void(*Hashtable_PairFunction)(int, void*, void*); typedef void(*Hashtable_PairFunction)(int, void*, void*);
typedef int(*Hashtable_HashAlgorithm)(Hashtable*, int);
typedef struct HashtableItem { typedef struct HashtableItem {
int key; unsigned int key;
void* value; void* value;
struct HashtableItem* next; struct HashtableItem* next;
} HashtableItem; } HashtableItem;
@ -28,12 +28,40 @@ struct Hashtable_ {
int size; int size;
HashtableItem** buckets; HashtableItem** buckets;
int items; int items;
Hashtable_HashAlgorithm hashAlgorithm;
bool owner; bool owner;
}; };
}*/ }*/
HashtableItem* HashtableItem_new(int key, void* value) { #ifdef DEBUG
static bool Hashtable_isConsistent(Hashtable* this) {
int items = 0;
for (int i = 0; i < this->size; i++) {
HashtableItem* bucket = this->buckets[i];
while (bucket) {
items++;
bucket = bucket->next;
}
}
return items == this->items;
}
int Hashtable_count(Hashtable* this) {
int items = 0;
for (int i = 0; i < this->size; i++) {
HashtableItem* bucket = this->buckets[i];
while (bucket) {
items++;
bucket = bucket->next;
}
}
assert(items == this->items);
return items;
}
#endif
static HashtableItem* HashtableItem_new(unsigned int key, void* value) {
HashtableItem* this; HashtableItem* this;
this = (HashtableItem*) malloc(sizeof(HashtableItem)); this = (HashtableItem*) malloc(sizeof(HashtableItem));
@ -47,18 +75,16 @@ Hashtable* Hashtable_new(int size, bool owner) {
Hashtable* this; Hashtable* this;
this = (Hashtable*) malloc(sizeof(Hashtable)); this = (Hashtable*) malloc(sizeof(Hashtable));
this->items = 0;
this->size = size; this->size = size;
this->buckets = (HashtableItem**) calloc(sizeof(HashtableItem*), size); this->buckets = (HashtableItem**) calloc(sizeof(HashtableItem*), size);
this->hashAlgorithm = Hashtable_hashAlgorithm;
this->owner = owner; this->owner = owner;
assert(Hashtable_isConsistent(this));
return this; return this;
} }
int Hashtable_hashAlgorithm(Hashtable* this, int key) {
return (key % this->size);
}
void Hashtable_delete(Hashtable* this) { void Hashtable_delete(Hashtable* this) {
assert(Hashtable_isConsistent(this));
for (int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
HashtableItem* walk = this->buckets[i]; HashtableItem* walk = this->buckets[i];
while (walk != NULL) { while (walk != NULL) {
@ -73,12 +99,8 @@ void Hashtable_delete(Hashtable* this) {
free(this); free(this);
} }
inline int Hashtable_size(Hashtable* this) { void Hashtable_put(Hashtable* this, unsigned int key, void* value) {
return this->items; unsigned int index = key % this->size;
}
void Hashtable_put(Hashtable* this, int key, void* value) {
int index = this->hashAlgorithm(this, key);
HashtableItem** bucketPtr = &(this->buckets[index]); HashtableItem** bucketPtr = &(this->buckets[index]);
while (true) while (true)
if (*bucketPtr == NULL) { if (*bucketPtr == NULL) {
@ -92,44 +114,53 @@ void Hashtable_put(Hashtable* this, int key, void* value) {
break; break;
} else } else
bucketPtr = &((*bucketPtr)->next); bucketPtr = &((*bucketPtr)->next);
assert(Hashtable_isConsistent(this));
} }
void* Hashtable_remove(Hashtable* this, int key) { void* Hashtable_remove(Hashtable* this, unsigned int key) {
int index = this->hashAlgorithm(this, key); unsigned int index = key % this->size;
HashtableItem** bucketPtr = &(this->buckets[index]);
while (true) assert(Hashtable_isConsistent(this));
if (*bucketPtr == NULL) {
return NULL; HashtableItem** bucket;
break; for (bucket = &(this->buckets[index]); *bucket; bucket = &((*bucket)->next) ) {
} else if ((*bucketPtr)->key == key) { if ((*bucket)->key == key) {
void* savedValue = (*bucketPtr)->value; void* value = (*bucket)->value;
HashtableItem* savedNext = (*bucketPtr)->next; HashtableItem* next = (*bucket)->next;
free(*bucketPtr); free(*bucket);
(*bucketPtr) = savedNext; (*bucket) = next;
this->items--; this->items--;
if (this->owner) { if (this->owner) {
free(savedValue); free(value);
assert(Hashtable_isConsistent(this));
return NULL; return NULL;
} else { } else {
return savedValue; assert(Hashtable_isConsistent(this));
return value;
} }
} else }
bucketPtr = &((*bucketPtr)->next); }
assert(Hashtable_isConsistent(this));
return NULL;
} }
inline void* Hashtable_get(Hashtable* this, int key) { inline void* Hashtable_get(Hashtable* this, unsigned int key) {
int index = this->hashAlgorithm(this, key); unsigned int index = key % this->size;
HashtableItem* bucketPtr = this->buckets[index]; HashtableItem* bucketPtr = this->buckets[index];
while (true) while (true) {
if (bucketPtr == NULL) { if (bucketPtr == NULL) {
assert(Hashtable_isConsistent(this));
return NULL; return NULL;
} else if (bucketPtr->key == key) { } else if (bucketPtr->key == key) {
assert(Hashtable_isConsistent(this));
return bucketPtr->value; return bucketPtr->value;
} else } else
bucketPtr = bucketPtr->next; bucketPtr = bucketPtr->next;
}
} }
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) { void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
assert(Hashtable_isConsistent(this));
for (int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
HashtableItem* walk = this->buckets[i]; HashtableItem* walk = this->buckets[i];
while (walk != NULL) { while (walk != NULL) {
@ -137,4 +168,5 @@ void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData
walk = walk->next; walk = walk->next;
} }
} }
assert(Hashtable_isConsistent(this));
} }

View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Hashtable #ifndef HEADER_Hashtable
#define HEADER_Hashtable #define HEADER_Hashtable
@ -12,16 +12,16 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h>
#include "debug.h" #include "debug.h"
typedef struct Hashtable_ Hashtable; typedef struct Hashtable_ Hashtable;
typedef void(*Hashtable_PairFunction)(int, void*, void*); typedef void(*Hashtable_PairFunction)(int, void*, void*);
typedef int(*Hashtable_HashAlgorithm)(Hashtable*, int);
typedef struct HashtableItem { typedef struct HashtableItem {
int key; unsigned int key;
void* value; void* value;
struct HashtableItem* next; struct HashtableItem* next;
} HashtableItem; } HashtableItem;
@ -30,25 +30,24 @@ struct Hashtable_ {
int size; int size;
HashtableItem** buckets; HashtableItem** buckets;
int items; int items;
Hashtable_HashAlgorithm hashAlgorithm;
bool owner; bool owner;
}; };
HashtableItem* HashtableItem_new(int key, void* value); #ifdef DEBUG
int Hashtable_count(Hashtable* this);
#endif
Hashtable* Hashtable_new(int size, bool owner); Hashtable* Hashtable_new(int size, bool owner);
int Hashtable_hashAlgorithm(Hashtable* this, int key);
void Hashtable_delete(Hashtable* this); void Hashtable_delete(Hashtable* this);
inline int Hashtable_size(Hashtable* this); void Hashtable_put(Hashtable* this, unsigned int key, void* value);
void Hashtable_put(Hashtable* this, int key, void* value); void* Hashtable_remove(Hashtable* this, unsigned int key);
void* Hashtable_remove(Hashtable* this, int key); extern void* Hashtable_get(Hashtable* this, unsigned int key);
inline void* Hashtable_get(Hashtable* this, int key);
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData); void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);

View File

@ -19,8 +19,8 @@ typedef enum HeaderSide_ {
} HeaderSide; } HeaderSide;
typedef struct Header_ { typedef struct Header_ {
TypedVector* leftMeters; Vector* leftMeters;
TypedVector* rightMeters; Vector* rightMeters;
ProcessList* pl; ProcessList* pl;
bool margin; bool margin;
int height; int height;
@ -35,21 +35,21 @@ typedef struct Header_ {
Header* Header_new(ProcessList* pl) { Header* Header_new(ProcessList* pl) {
Header* this = malloc(sizeof(Header)); Header* this = malloc(sizeof(Header));
this->leftMeters = TypedVector_new(METER_CLASS, true, DEFAULT_SIZE); this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->rightMeters = TypedVector_new(METER_CLASS, true, DEFAULT_SIZE); this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->margin = true; this->margin = true;
this->pl = pl; this->pl = pl;
return this; return this;
} }
void Header_delete(Header* this) { void Header_delete(Header* this) {
TypedVector_delete(this->leftMeters); Vector_delete(this->leftMeters);
TypedVector_delete(this->rightMeters); Vector_delete(this->rightMeters);
free(this); free(this);
} }
void Header_createMeter(Header* this, char* name, HeaderSide side) { void Header_createMeter(Header* this, char* name, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
@ -62,44 +62,46 @@ void Header_createMeter(Header* this, char* name, HeaderSide side) {
} }
for (MeterType** type = Meter_types; *type; type++) { for (MeterType** type = Meter_types; *type; type++) {
if (String_eq(name, (*type)->name)) { if (String_eq(name, (*type)->name)) {
TypedVector_add(meters, Meter_new(this->pl, param, *type)); Vector_add(meters, Meter_new(this->pl, param, *type));
break; break;
} }
} }
} }
void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side) { void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
Meter* meter = (Meter*) TypedVector_get(meters, i); if (i >= Vector_size(meters))
return;
Meter* meter = (Meter*) Vector_get(meters, i);
Meter_setMode(meter, mode); Meter_setMode(meter, mode);
} }
Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side) { Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
Meter* meter = Meter_new(this->pl, param, type); Meter* meter = Meter_new(this->pl, param, type);
TypedVector_add(meters, meter); Vector_add(meters, meter);
return meter; return meter;
} }
int Header_size(Header* this, HeaderSide side) { int Header_size(Header* this, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
return TypedVector_size(meters); return Vector_size(meters);
} }
char* Header_readMeterName(Header* this, int i, HeaderSide side) { char* Header_readMeterName(Header* this, int i, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
Meter* meter = (Meter*) TypedVector_get(meters, i); Meter* meter = (Meter*) Vector_get(meters, i);
int nameLen = strlen(meter->type->name); int nameLen = strlen(meter->type->name);
int len = nameLen + 100; int len = nameLen + 100;
@ -113,21 +115,21 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side) {
} }
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) { MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) {
TypedVector* meters = side == LEFT_HEADER Vector* meters = side == LEFT_HEADER
? this->leftMeters ? this->leftMeters
: this->rightMeters; : this->rightMeters;
Meter* meter = (Meter*) TypedVector_get(meters, i); Meter* meter = (Meter*) Vector_get(meters, i);
return meter->mode; return meter->mode;
} }
void Header_defaultMeters(Header* this) { void Header_defaultMeters(Header* this) {
TypedVector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter)); Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
TypedVector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter)); Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
TypedVector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter)); Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
TypedVector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter)); Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
TypedVector_add(this->rightMeters, Meter_new(this->pl, 0, &LoadAverageMeter)); Vector_add(this->rightMeters, Meter_new(this->pl, 0, &LoadAverageMeter));
TypedVector_add(this->rightMeters, Meter_new(this->pl, 0, &UptimeMeter)); Vector_add(this->rightMeters, Meter_new(this->pl, 0, &UptimeMeter));
} }
void Header_draw(Header* this) { void Header_draw(Header* this) {
@ -138,13 +140,13 @@ void Header_draw(Header* this) {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
mvhline(y, 0, ' ', COLS); mvhline(y, 0, ' ', COLS);
} }
for (int y = (pad / 2), i = 0; i < TypedVector_size(this->leftMeters); i++) { for (int y = (pad / 2), i = 0; i < Vector_size(this->leftMeters); i++) {
Meter* meter = (Meter*) TypedVector_get(this->leftMeters, i); Meter* meter = (Meter*) Vector_get(this->leftMeters, i);
meter->draw(meter, pad, y, COLS / 2 - (pad * 2 - 1) - 1); meter->draw(meter, pad, y, COLS / 2 - (pad * 2 - 1) - 1);
y += meter->h; y += meter->h;
} }
for (int y = (pad / 2), i = 0; i < TypedVector_size(this->rightMeters); i++) { for (int y = (pad / 2), i = 0; i < Vector_size(this->rightMeters); i++) {
Meter* meter = (Meter*) TypedVector_get(this->rightMeters, i); Meter* meter = (Meter*) Vector_get(this->rightMeters, i);
meter->draw(meter, COLS / 2 + pad, y, COLS / 2 - (pad * 2 - 1) - 1); meter->draw(meter, COLS / 2 + pad, y, COLS / 2 - (pad * 2 - 1) - 1);
y += meter->h; y += meter->h;
} }
@ -155,12 +157,12 @@ int Header_calculateHeight(Header* this) {
int leftHeight = pad; int leftHeight = pad;
int rightHeight = pad; int rightHeight = pad;
for (int i = 0; i < TypedVector_size(this->leftMeters); i++) { for (int i = 0; i < Vector_size(this->leftMeters); i++) {
Meter* meter = (Meter*) TypedVector_get(this->leftMeters, i); Meter* meter = (Meter*) Vector_get(this->leftMeters, i);
leftHeight += meter->h; leftHeight += meter->h;
} }
for (int i = 0; i < TypedVector_size(this->rightMeters); i++) { for (int i = 0; i < Vector_size(this->rightMeters); i++) {
Meter* meter = (Meter*) TypedVector_get(this->rightMeters, i); Meter* meter = (Meter*) Vector_get(this->rightMeters, i);
rightHeight += meter->h; rightHeight += meter->h;
} }
this->pad = pad; this->pad = pad;

View File

@ -3,7 +3,7 @@
#ifndef HEADER_Header #ifndef HEADER_Header
#define HEADER_Header #define HEADER_Header
/* /*
htop - Header.c htop - Header.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -21,8 +21,8 @@ typedef enum HeaderSide_ {
} HeaderSide; } HeaderSide;
typedef struct Header_ { typedef struct Header_ {
TypedVector* leftMeters; Vector* leftMeters;
TypedVector* rightMeters; Vector* rightMeters;
ProcessList* pl; ProcessList* pl;
bool margin; bool margin;
int height; int height;

33
HostnameMeter.c Normal file
View File

@ -0,0 +1,33 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "HostnameMeter.h"
#include "Meter.h"
#include <unistd.h>
#include "debug.h"
int HostnameMeter_attributes[] = {
HOSTNAME
};
static void HostnameMeter_setValues(Meter* this, char* buffer, int size) {
gethostname(buffer, size-1);
}
MeterType HostnameMeter = {
.setValues = HostnameMeter_setValues,
.display = NULL,
.mode = TEXT_METERMODE,
.total = 100.0,
.items = 1,
.attributes = HostnameMeter_attributes,
.name = "Hostname",
.uiName = "Hostname",
.caption = "Hostname: ",
};

22
HostnameMeter.h Normal file
View File

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

353
ListBox.c
View File

@ -1,353 +0,0 @@
/*
htop - ListBox.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 "Object.h"
#include "ListBox.h"
#include "TypedVector.h"
#include "CRT.h"
#include "RichString.h"
#include <math.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
/*{
typedef struct ListBox_ ListBox;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
typedef HandlerResult(*ListBox_EventHandler)(ListBox*, int);
struct ListBox_ {
Object super;
int x, y, w, h;
WINDOW* window;
TypedVector* items;
int selected;
int scrollV, scrollH;
int oldSelected;
bool needsRedraw;
RichString header;
ListBox_EventHandler eventHandler;
};
extern char* LISTBOX_CLASS;
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
/* private property */
char* LISTBOX_CLASS = "ListBox";
ListBox* ListBox_new(int x, int y, int w, int h, char* type, bool owner) {
ListBox* this;
this = malloc(sizeof(ListBox));
ListBox_init(this, x, y, w, h, type, owner);
return this;
}
void ListBox_delete(Object* cast) {
ListBox* this = (ListBox*)cast;
ListBox_done(this);
free(this);
}
void ListBox_init(ListBox* this, int x, int y, int w, int h, char* type, bool owner) {
Object* super = (Object*) this;
super->class = LISTBOX_CLASS;
super->delete = ListBox_delete;
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->eventHandler = NULL;
this->items = TypedVector_new(type, owner, DEFAULT_SIZE);
this->scrollV = 0;
this->scrollH = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
this->header.len = 0;
}
void ListBox_done(ListBox* this) {
assert (this != NULL);
RichString_delete(this->header);
TypedVector_delete(this->items);
}
inline void ListBox_setRichHeader(ListBox* this, RichString header) {
assert (this != NULL);
if (this->header.len > 0) {
RichString_delete(this->header);
}
this->header = header;
this->needsRedraw = true;
}
inline void ListBox_setHeader(ListBox* this, char* header) {
ListBox_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
}
void ListBox_setEventHandler(ListBox* this, ListBox_EventHandler eh) {
this->eventHandler = eh;
}
void ListBox_move(ListBox* this, int x, int y) {
assert (this != NULL);
this->x = x;
this->y = y;
this->needsRedraw = true;
}
void ListBox_resize(ListBox* this, int w, int h) {
assert (this != NULL);
if (this->header.len > 0)
h--;
this->w = w;
this->h = h;
this->needsRedraw = true;
}
void ListBox_prune(ListBox* this) {
assert (this != NULL);
TypedVector_prune(this->items);
this->scrollV = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
}
void ListBox_add(ListBox* this, Object* o) {
assert (this != NULL);
TypedVector_add(this->items, o);
this->needsRedraw = true;
}
void ListBox_insert(ListBox* this, int i, Object* o) {
assert (this != NULL);
TypedVector_insert(this->items, i, o);
this->needsRedraw = true;
}
void ListBox_set(ListBox* this, int i, Object* o) {
assert (this != NULL);
TypedVector_set(this->items, i, o);
}
Object* ListBox_get(ListBox* this, int i) {
assert (this != NULL);
return TypedVector_get(this->items, i);
}
Object* ListBox_remove(ListBox* this, int i) {
assert (this != NULL);
this->needsRedraw = true;
Object* removed = TypedVector_remove(this->items, i);
if (this->selected > 0 && this->selected >= TypedVector_size(this->items))
this->selected--;
return removed;
}
Object* ListBox_getSelected(ListBox* this) {
assert (this != NULL);
return TypedVector_get(this->items, this->selected);
}
void ListBox_moveSelectedUp(ListBox* this) {
assert (this != NULL);
TypedVector_moveUp(this->items, this->selected);
if (this->selected > 0)
this->selected--;
}
void ListBox_moveSelectedDown(ListBox* this) {
assert (this != NULL);
TypedVector_moveDown(this->items, this->selected);
if (this->selected + 1 < TypedVector_size(this->items))
this->selected++;
}
int ListBox_getSelectedIndex(ListBox* this) {
assert (this != NULL);
return this->selected;
}
int ListBox_getSize(ListBox* this) {
assert (this != NULL);
return TypedVector_size(this->items);
}
void ListBox_setSelected(ListBox* this, int selected) {
assert (this != NULL);
selected = MAX(0, MIN(TypedVector_size(this->items) - 1, selected));
this->selected = selected;
}
void ListBox_draw(ListBox* this, bool focus) {
assert (this != NULL);
int first, last;
int itemCount = TypedVector_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);
}
if (this->selected < first) {
first = this->selected;
this->scrollV = first;
this->needsRedraw = true;
}
if (this->selected >= last) {
last = MIN(itemCount, this->selected + 1);
first = MAX(0, last - this->h);
this->scrollV = first;
this->needsRedraw = true;
}
assert(first >= 0);
assert(last <= itemCount);
if (this->header.len > 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));
}
attrset(CRT_colors[RESET_COLOR]);
y++;
}
int highlight = focus
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
if (this->needsRedraw) {
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
Object* itemObj = TypedVector_get(this->items, i);
RichString itemRef = RichString_new();
itemObj->display(itemObj, &itemRef);
int amt = MIN(itemRef.len - scrollH, this->w);
if (i == this->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);
}
}
for (int i = y + (last - first); i < y + this->h; i++)
mvhline(i, x+0, ' ', this->w);
this->needsRedraw = false;
} else {
Object* oldObj = TypedVector_get(this->items, this->oldSelected);
RichString oldRef = RichString_new();
oldObj->display(oldObj, &oldRef);
Object* newObj = TypedVector_get(this->items, this->selected);
RichString newRef = RichString_new();
newObj->display(newObj, &newRef);
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));
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));
attrset(CRT_colors[RESET_COLOR]);
}
this->oldSelected = this->selected;
move(0, 0);
}
void ListBox_onKey(ListBox* this, int key) {
assert (this != NULL);
switch (key) {
case KEY_DOWN:
if (this->selected + 1 < TypedVector_size(this->items))
this->selected++;
break;
case KEY_UP:
if (this->selected > 0)
this->selected--;
break;
case KEY_LEFT:
if (this->scrollH > 0) {
this->scrollH -= 5;
this->needsRedraw = true;
}
break;
case KEY_RIGHT:
this->scrollH += 5;
this->needsRedraw = true;
break;
case KEY_PPAGE:
this->selected -= this->h;
if (this->selected < 0)
this->selected = 0;
break;
case KEY_NPAGE:
this->selected += this->h;
int size = TypedVector_size(this->items);
if (this->selected >= size)
this->selected = size - 1;
break;
case KEY_HOME:
this->selected = 0;
break;
case KEY_END:
this->selected = TypedVector_size(this->items) - 1;
break;
}
}

101
ListBox.h
View File

@ -1,101 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_ListBox
#define HEADER_ListBox
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "TypedVector.h"
#include "CRT.h"
#include "RichString.h"
#include <math.h>
#include <sys/param.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
typedef struct ListBox_ ListBox;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
typedef HandlerResult(*ListBox_EventHandler)(ListBox*, int);
struct ListBox_ {
Object super;
int x, y, w, h;
WINDOW* window;
TypedVector* items;
int selected;
int scrollV, scrollH;
int oldSelected;
bool needsRedraw;
RichString header;
ListBox_EventHandler eventHandler;
};
extern char* LISTBOX_CLASS;
ListBox* ListBox_new(int x, int y, int w, int h, char* type, bool owner);
void ListBox_delete(Object* cast);
void ListBox_init(ListBox* this, int x, int y, int w, int h, char* type, bool owner);
void ListBox_done(ListBox* this);
void ListBox_setEventHandler(ListBox* this, ListBox_EventHandler eh);
void ListBox_setRichHeader(ListBox* this, RichString header);
void ListBox_setHeader(ListBox* this, char* header);
void ListBox_move(ListBox* this, int x, int y);
void ListBox_resize(ListBox* this, int w, int h);
void ListBox_prune(ListBox* this);
void ListBox_add(ListBox* this, Object* o);
void ListBox_insert(ListBox* this, int i, Object* o);
void ListBox_set(ListBox* this, int i, Object* o);
Object* ListBox_get(ListBox* this, int i);
Object* ListBox_remove(ListBox* this, int i);
Object* ListBox_getSelected(ListBox* this);
void ListBox_moveSelectedUp(ListBox* this);
void ListBox_moveSelectedDown(ListBox* this);
int ListBox_getSelectedIndex(ListBox* this);
int ListBox_getSize(ListBox* this);
void ListBox_setSelected(ListBox* this, int selected);
void ListBox_draw(ListBox* this, bool focus);
void ListBox_onKey(ListBox* this, int key);
#endif

View File

@ -21,18 +21,34 @@ typedef struct ListItem_ {
int key; int key;
} ListItem; } ListItem;
extern char* LISTITEM_CLASS;
}*/ }*/
/* private property */ #ifdef DEBUG
char* LISTITEM_CLASS = "ListItem"; char* LISTITEM_CLASS = "ListItem";
#else
#define LISTITEM_CLASS NULL
#endif
static void ListItem_delete(Object* cast) {
ListItem* this = (ListItem*)cast;
free(this->value);
free(this);
}
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);
}
ListItem* ListItem_new(char* value, int key) { ListItem* ListItem_new(char* value, int key) {
ListItem* this = malloc(sizeof(ListItem)); ListItem* this = malloc(sizeof(ListItem));
((Object*)this)->class = LISTITEM_CLASS; Object_setClass(this, LISTITEM_CLASS);
((Object*)this)->display = ListItem_display; ((Object*)this)->display = ListItem_display;
((Object*)this)->delete = ListItem_delete; ((Object*)this)->delete = ListItem_delete;
((Object*)this)->compare = ListItem_compare;
this->value = String_copy(value); this->value = String_copy(value);
this->key = key; this->key = key;
return this; return this;
@ -45,26 +61,11 @@ void ListItem_append(ListItem* this, char* text) {
this->value = buf; this->value = buf;
} }
void ListItem_delete(Object* cast) {
ListItem* this = (ListItem*)cast;
free(this->value);
free(this);
}
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);
}
const char* ListItem_getRef(ListItem* this) { const char* ListItem_getRef(ListItem* this) {
return this->value; return this->value;
} }
int ListItem_compare(const Object* cast1, const Object* cast2) { int ListItem_compare(const void* cast1, const void* cast2) {
ListItem* obj1 = (ListItem*) cast1; ListItem* obj1 = (ListItem*) cast1;
ListItem* obj2 = (ListItem*) cast2; ListItem* obj2 = (ListItem*) cast2;
return strcmp(obj1->value, obj2->value); return strcmp(obj1->value, obj2->value);

View File

@ -1,9 +1,9 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ListItem #ifndef HEADER_ListItem
#define HEADER_ListItem #define HEADER_ListItem
/* /*
htop htop - ListItem.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -16,24 +16,27 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
typedef struct ListItem_ { typedef struct ListItem_ {
Object super; Object super;
char* value; char* value;
int key; int key;
} ListItem; } ListItem;
#ifdef DEBUG
extern char* LISTITEM_CLASS; extern char* LISTITEM_CLASS;
#else
#define LISTITEM_CLASS NULL
#endif
ListItem* ListItem_new(char* value, int key); ListItem* ListItem_new(char* value, int key);
void ListItem_delete(Object* cast);
void ListItem_display(Object* cast, RichString* out);
void ListItem_append(ListItem* this, char* text); void ListItem_append(ListItem* this, char* text);
const char* ListItem_getRef(ListItem* this); const char* ListItem_getRef(ListItem* this);
int ListItem_compare(const Object*, const Object*); int ListItem_compare(const void* cast1, const void* cast2);
#endif #endif

View File

@ -12,10 +12,56 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
/* private property */ int LoadAverageMeter_attributes[] = {
int LoadAverageMeter_attributes[] = { LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE }; LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE
};
int LoadMeter_attributes[] = { LOAD };
static inline void LoadAverageMeter_scan(double* one, double* five, double* fifteen) {
int activeProcs, totalProcs, lastProc;
FILE *fd = fopen(PROCDIR "/loadavg", "r");
int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
&activeProcs, &totalProcs, &lastProc);
(void) read;
assert(read == 6);
fclose(fd);
}
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]);
}
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);
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);
}
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) {
this->total = this->values[0];
}
snprintf(buffer, size, "%.2f", this->values[0]);
}
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);
}
/* private */
MeterType LoadAverageMeter = { MeterType LoadAverageMeter = {
.setValues = LoadAverageMeter_setValues, .setValues = LoadAverageMeter_setValues,
.display = LoadAverageMeter_display, .display = LoadAverageMeter_display,
@ -28,10 +74,6 @@ MeterType LoadAverageMeter = {
.caption = "Load average: " .caption = "Load average: "
}; };
/* private property */
int LoadMeter_attributes[] = { LOAD };
/* private */
MeterType LoadMeter = { MeterType LoadMeter = {
.setValues = LoadMeter_setValues, .setValues = LoadMeter_setValues,
.display = LoadMeter_display, .display = LoadMeter_display,
@ -43,48 +85,3 @@ MeterType LoadMeter = {
.uiName = "Load", .uiName = "Load",
.caption = "Load: " .caption = "Load: "
}; };
/* private */
inline static void LoadAverageMeter_scan(double* one, double* five, double* fifteen) {
int activeProcs, totalProcs, lastProc;
FILE *fd = fopen(PROCDIR "/loadavg", "r");
int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
&activeProcs, &totalProcs, &lastProc);
(void) read;
assert(read == 6);
fclose(fd);
}
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) {
Meter* this = (Meter*)cast;
char buffer[20];
RichString_prune(out);
sprintf(buffer, "%.2f ", this->values[2]);
RichString_append(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) {
double five, fifteen;
LoadAverageMeter_scan(&this->values[0], &five, &fifteen);
if (this->values[0] > this->total) {
this->total = this->values[0];
}
snprintf(buffer, size, "%.2f", this->values[0]);
}
void LoadMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
char buffer[20];
RichString_prune(out);
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
RichString_append(out, CRT_colors[LOAD], buffer);
}

View File

@ -15,17 +15,12 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
extern int LoadAverageMeter_attributes[];
extern int LoadMeter_attributes[];
extern MeterType LoadAverageMeter;
extern MeterType LoadMeter;
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);
#endif #endif

View File

@ -1,63 +0,0 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "LoadMeter.h"
#include "Meter.h"
#include "ProcessList.h"
#include "debug.h"
/*{
typedef struct LoadMeter_ LoadMeter;
struct LoadMeter_ {
Meter super;
ProcessList* pl;
};
}*/
LoadMeter* LoadMeter_new() {
LoadMeter* this = malloc(sizeof(LoadMeter));
Meter_init((Meter*)this, String_copy("Load"), String_copy("Load: "), 1);
((Meter*)this)->attributes[0] = LOAD;
((Meter*)this)->setValues = LoadMeter_setValues;
((Object*)this)->display = LoadMeter_display;
Meter_setMode((Meter*)this, GRAPH);
((Meter*)this)->total = 1.0;
return this;
}
/* private */
void LoadMeter_scan(double* one, double* five, double* fifteen) {
int activeProcs, totalProcs, lastProc;
FILE *fd = fopen(PROCDIR "/loadavg", "r");
int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
&activeProcs, &totalProcs, &lastProc);
(void) read;
assert(read == 6);
fclose(fd);
}
void LoadMeter_setValues(Meter* cast) {
double five, fifteen;
LoadMeter_scan(&cast->values[0], &five, &fifteen);
if (cast->values[0] > cast->total) {
cast->total = cast->values[0];
}
snprintf(cast->displayBuffer.c, 7, "%.2f", cast->values[0]);
}
void LoadMeter_display(Object* cast, RichString* out) {
LoadMeter* this = (LoadMeter*)cast;
char buffer[20];
RichString_prune(out);
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
RichString_append(out, CRT_colors[LOAD], buffer);
}

View File

@ -1,34 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_LoadMeter
#define HEADER_LoadMeter
/*
htop
(C) 2004-2006 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 "debug.h"
typedef struct LoadMeter_ LoadMeter;
struct LoadMeter_ {
Meter super;
ProcessList* pl;
};
LoadMeter* LoadMeter_new();
void LoadMeter_setValues(Meter* cast);
void LoadMeter_display(Object* cast, RichString* out);
#endif

View File

@ -1,31 +1,60 @@
if HAVE_PLPA
SUBDIRS = plpa-1.1
endif
bin_PROGRAMS = htop bin_PROGRAMS = htop
dist_man_MANS = htop.1 dist_man_MANS = htop.1
EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py \
install-sh autogen.sh missing
applicationsdir = $(datadir)/applications applicationsdir = $(datadir)/applications
applications_DATA = htop.desktop applications_DATA = htop.desktop
pixmapdir = $(datadir)/pixmaps pixmapdir = $(datadir)/pixmaps
pixmap_DATA = htop.png pixmap_DATA = htop.png
AM_CFLAGS = -pedantic -Wall -std=c99 htop_CFLAGS = -pedantic -Wall -std=c99 -D_XOPEN_SOURCE_EXTENDED
AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
htop_SOURCES = AvailableMetersListBox.c CategoriesListBox.c ClockMeter.c \ myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \
CPUMeter.c CRT.c DebugMemory.c DisplayOptionsListBox.c FunctionBar.c \ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c DebugMemory.c \
Hashtable.c Header.c htop.c ListBox.c ListItem.c LoadAverageMeter.c \ DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
MemoryMeter.c Meter.c MetersListBox.c Object.c Process.c \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
ProcessList.c RichString.c ScreenManager.c Settings.c SignalItem.c \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalsListBox.c String.c SwapMeter.c TasksMeter.c TypedVector.c \ SignalItem.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
UptimeMeter.c UsersTable.c AvailableMetersListBox.h CategoriesListBox.h \ UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
ClockMeter.h config.h CPUMeter.h CRT.h debug.h DebugMemory.h \ HostnameMeter.c OpenFilesScreen.c
DisplayOptionsListBox.h FunctionBar.h Hashtable.h Header.h htop.h ListBox.h \
ListItem.h LoadAverageMeter.h MemoryMeter.h Meter.h \ myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
MetersListBox.h Object.h Process.h ProcessList.h RichString.h ScreenManager.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
Settings.h SignalItem.h SignalsListBox.h String.h SwapMeter.h TasksMeter.h \ CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \
TypedVector.h UptimeMeter.h UsersTable.h CheckItem.c CheckItem.h \ Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
ColorsListBox.c ColorsListBox.h TraceScreen.c TraceScreen.h \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
AvailableColumnsListBox.c AvailableColumnsListBox.h ColumnsListBox.c \ ScreenManager.h Settings.h SignalItem.h SignalsPanel.h String.h \
ColumnsListBox.h SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
Process.h AffinityPanel.h HostnameMeter.h OpenFilesScreen.h
SUFFIXES = .h
BUILT_SOURCES = $(myhtopheaders)
htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h debug.h
if HAVE_PLPA
htop_LDADD = $(top_builddir)/plpa-1.1/src/libplpa_included.la
endif
profile:
$(MAKE) all CFLAGS="-pg -O2"
debug: debug:
$(MAKE) all CFLAGS="-g -DDEBUG" $(MAKE) all CFLAGS="-ggdb -DDEBUG"
hardened-debug:
$(MAKE) all CFLAGS="-ggdb -DDEBUG" LDFLAGS="-nopie"
debuglite:
$(MAKE) all CFLAGS="-ggdb -DDEBUGLITE"
.c.h:
scripts/MakeHeader.py $<

View File

@ -19,23 +19,11 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
/* private property */ int MemoryMeter_attributes[] = {
static int MemoryMeter_attributes[] = { MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE }; MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE
/* private */
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 usedMem = this->pl->usedMem;
long int buffersMem = this->pl->buffersMem; long int buffersMem = this->pl->buffersMem;
long int cachedMem = this->pl->cachedMem; long int cachedMem = this->pl->cachedMem;
@ -47,7 +35,7 @@ void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024); 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]; char buffer[50];
Meter* this = (Meter*)cast; Meter* this = (Meter*)cast;
int div = 1024; char* format = "%ldM "; int div = 1024; char* format = "%ldM ";
@ -55,7 +43,7 @@ void MemoryMeter_display(Object* cast, RichString* out) {
long int usedMem = this->values[0] / div; long int usedMem = this->values[0] / div;
long int buffersMem = this->values[1] / div; long int buffersMem = this->values[1] / div;
long int cachedMem = this->values[2] / div; long int cachedMem = this->values[2] / div;
RichString_prune(out); RichString_init(out);
RichString_append(out, CRT_colors[METER_TEXT], ":"); RichString_append(out, CRT_colors[METER_TEXT], ":");
sprintf(buffer, format, totalMem); sprintf(buffer, format, totalMem);
RichString_append(out, CRT_colors[METER_VALUE], buffer); RichString_append(out, CRT_colors[METER_VALUE], buffer);
@ -69,3 +57,15 @@ void MemoryMeter_display(Object* cast, RichString* out) {
RichString_append(out, CRT_colors[METER_TEXT], "cache:"); RichString_append(out, CRT_colors[METER_TEXT], "cache:");
RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); RichString_append(out, CRT_colors[MEMORY_CACHE], buffer);
} }
MeterType MemoryMeter = {
.setValues = MemoryMeter_setValues,
.display = MemoryMeter_display,
.mode = BAR_METERMODE,
.items = 3,
.total = 100.0,
.attributes = MemoryMeter_attributes,
"Memory",
"Memory",
"Mem"
};

View File

@ -22,10 +22,8 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.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);
#endif #endif

174
Meter.c
View File

@ -6,12 +6,7 @@ in the source distribution for its full text.
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <math.h> #include "RichString.h"
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "Meter.h" #include "Meter.h"
#include "Object.h" #include "Object.h"
#include "CRT.h" #include "CRT.h"
@ -19,6 +14,11 @@ in the source distribution for its full text.
#include "String.h" #include "String.h"
#include "ProcessList.h" #include "ProcessList.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -76,18 +76,6 @@ struct Meter_ {
double total; double total;
}; };
extern char* METER_CLASS;
extern MeterType CPUMeter;
extern MeterType ClockMeter;
extern MeterType LoadAverageMeter;
extern MeterType LoadMeter;
extern MeterType MemoryMeter;
extern MeterType SwapMeter;
extern MeterType TasksMeter;
extern MeterType UptimeMeter;
extern MeterType AllCPUsMeter;
typedef enum { typedef enum {
CUSTOM_METERMODE = 0, CUSTOM_METERMODE = 0,
BAR_METERMODE, BAR_METERMODE,
@ -99,11 +87,19 @@ typedef enum {
LAST_METERMODE LAST_METERMODE
} MeterModeId; } MeterModeId;
extern MeterType* Meter_types[];
extern MeterMode* Meter_modes[];
}*/ }*/
#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"
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
@ -111,10 +107,12 @@ extern MeterMode* Meter_modes[];
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
/* private property */ #ifdef DEBUG
char* METER_CLASS = "Meter"; char* METER_CLASS = "Meter";
#else
#define METER_CLASS NULL
#endif
/* private */
MeterType* Meter_types[] = { MeterType* Meter_types[] = {
&CPUMeter, &CPUMeter,
&ClockMeter, &ClockMeter,
@ -124,57 +122,19 @@ MeterType* Meter_types[] = {
&SwapMeter, &SwapMeter,
&TasksMeter, &TasksMeter,
&UptimeMeter, &UptimeMeter,
&BatteryMeter,
&AllCPUsMeter, &AllCPUsMeter,
&HostnameMeter,
NULL NULL
}; };
/* private */
static MeterMode BarMeterMode = {
.uiName = "Bar",
.h = 1,
.draw = BarMeterMode_draw,
};
/* private */
static MeterMode TextMeterMode = {
.uiName = "Text",
.h = 1,
.draw = TextMeterMode_draw,
};
#ifdef USE_FUNKY_MODES
/* private */
static MeterMode GraphMeterMode = {
.uiName = "Graph",
.h = 3,
.draw = GraphMeterMode_draw,
};
/* private */
static MeterMode LEDMeterMode = {
.uiName = "LED",
.h = 3,
.draw = LEDMeterMode_draw,
};
#endif
/* private */
MeterMode* Meter_modes[] = {
NULL,
&BarMeterMode,
&TextMeterMode,
#ifdef USE_FUNKY_MODES
&GraphMeterMode,
&LEDMeterMode,
#endif
NULL
};
/* private property */
static RichString Meter_stringBuffer; static RichString Meter_stringBuffer;
Meter* Meter_new(ProcessList* pl, int param, MeterType* type) { Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
Meter* this = calloc(sizeof(Meter), 1); Meter* this = calloc(sizeof(Meter), 1);
Object_setClass(this, METER_CLASS);
((Object*)this)->delete = Meter_delete;
((Object*)this)->display = type->display;
this->h = 1; this->h = 1;
this->type = type; this->type = type;
this->param = param; this->param = param;
@ -182,9 +142,6 @@ Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
this->values = calloc(sizeof(double), type->items); this->values = calloc(sizeof(double), type->items);
this->total = type->total; this->total = type->total;
this->caption = strdup(type->caption); this->caption = strdup(type->caption);
((Object*)this)->delete = Meter_delete;
((Object*)this)->class = METER_CLASS;
((Object*)this)->display = type->display;
Meter_setMode(this, type->mode); Meter_setMode(this, type->mode);
if (this->type->init) if (this->type->init)
this->type->init(this); this->type->init(this);
@ -209,14 +166,13 @@ void Meter_setCaption(Meter* this, char* caption) {
this->caption = strdup(caption); this->caption = strdup(caption);
} }
/* private */ static inline void Meter_displayToStringBuffer(Meter* this, char* buffer) {
inline static void Meter_displayToStringBuffer(Meter* this, char* buffer) {
MeterType* type = this->type; MeterType* type = this->type;
Object_Display display = ((Object*)this)->display; Object_Display display = ((Object*)this)->display;
if (display) { if (display) {
display((Object*)this, &Meter_stringBuffer); display((Object*)this, &Meter_stringBuffer);
} else { } else {
RichString_prune(&Meter_stringBuffer); RichString_initVal(Meter_stringBuffer);
RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer); RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer);
} }
} }
@ -263,7 +219,7 @@ ListItem* Meter_toListItem(Meter* this) {
/* ---------- TextMeterMode ---------- */ /* ---------- TextMeterMode ---------- */
void TextMeterMode_draw(Meter* this, int x, int y, int w) { static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type; MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
@ -276,23 +232,22 @@ void TextMeterMode_draw(Meter* this, int x, int y, int w) {
Meter_displayToStringBuffer(this, buffer); Meter_displayToStringBuffer(this, buffer);
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]); mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
mvaddchstr(y, x, Meter_stringBuffer.chstr); RichString_printVal(Meter_stringBuffer, y, x);
} }
/* ---------- BarMeterMode ---------- */ /* ---------- BarMeterMode ---------- */
/* private property */ static char BarMeterMode_characters[] = "|#*@$%&";
char BarMeterMode_characters[] = "|#*@$%&";
void BarMeterMode_draw(Meter* this, int x, int y, int w) { static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type; MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
w -= 2; w -= 2;
attrset(CRT_colors[METER_TEXT]); attrset(CRT_colors[METER_TEXT]);
mvaddstr(y, x, this->caption); int captionLen = 3;
int captionLen = strlen(this->caption); mvaddnstr(y, x, this->caption, captionLen);
x += captionLen; x += captionLen;
w -= captionLen; w -= captionLen;
attrset(CRT_colors[BAR_BORDER]); attrset(CRT_colors[BAR_BORDER]);
@ -360,17 +315,19 @@ void BarMeterMode_draw(Meter* this, int x, int y, int w) {
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0) #define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
/* private */ static int GraphMeterMode_colors[21] = {
static int GraphMeterMode_colors[21] = {GRAPH_1, GRAPH_1, GRAPH_1, GRAPH_1, GRAPH_1, GRAPH_1,
GRAPH_2, GRAPH_2, GRAPH_2, GRAPH_3, GRAPH_3, GRAPH_3, GRAPH_2, GRAPH_2, GRAPH_2,
GRAPH_4, GRAPH_4, GRAPH_4, GRAPH_5, GRAPH_5, GRAPH_6, GRAPH_3, GRAPH_3, GRAPH_3,
GRAPH_7, GRAPH_7, GRAPH_7, GRAPH_8, GRAPH_8, GRAPH_9 GRAPH_4, GRAPH_4, GRAPH_4,
GRAPH_5, GRAPH_5, GRAPH_6,
GRAPH_7, GRAPH_7, GRAPH_7,
GRAPH_8, GRAPH_8, GRAPH_9
}; };
/* private property */
static char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_"; static 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); if (!this->drawBuffer) this->drawBuffer = calloc(sizeof(double), METER_BUFFER_LEN);
double* drawBuffer = (double*) this->drawBuffer; double* drawBuffer = (double*) this->drawBuffer;
@ -405,20 +362,18 @@ void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
/* ---------- LEDMeterMode ---------- */ /* ---------- LEDMeterMode ---------- */
/* private */
static char* LEDMeterMode_digits[3][10] = { static char* LEDMeterMode_digits[3][10] = {
{ " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "}, { " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "},
{ "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"}, { "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"},
{ "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"}, { "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"},
}; };
/* private */
static void LEDMeterMode_drawDigit(int x, int y, int n) { static void LEDMeterMode_drawDigit(int x, int y, int n) {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
mvaddstr(y+i, x, LEDMeterMode_digits[i][n]); mvaddstr(y+i, x, LEDMeterMode_digits[i][n]);
} }
void LEDMeterMode_draw(Meter* this, int x, int y, int w) { static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type; MeterType* type = this->type;
char buffer[METER_BUFFER_LEN]; char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1); type->setValues(this, buffer, METER_BUFFER_LEN - 1);
@ -429,7 +384,7 @@ void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
mvaddstr(y+2, x, this->caption); mvaddstr(y+2, x, this->caption);
int xx = x + strlen(this->caption); int xx = x + strlen(this->caption);
for (int i = 0; i < Meter_stringBuffer.len; i++) { for (int i = 0; i < Meter_stringBuffer.len; i++) {
char c = Meter_stringBuffer.chstr[i]; char c = RichString_getCharVal(Meter_stringBuffer, i);
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
LEDMeterMode_drawDigit(xx, y, c-48); LEDMeterMode_drawDigit(xx, y, c-48);
xx += 4; xx += 4;
@ -442,3 +397,42 @@ void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
} }
#endif #endif
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
};

66
Meter.h
View File

@ -3,25 +3,25 @@
#ifndef HEADER_Meter #ifndef HEADER_Meter
#define HEADER_Meter #define HEADER_Meter
/* /*
htop - Meter.c htop - Meter.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <math.h> #include "RichString.h"
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "Object.h" #include "Object.h"
#include "CRT.h" #include "CRT.h"
#include "ListItem.h" #include "ListItem.h"
#include "String.h" #include "String.h"
#include "ProcessList.h" #include "ProcessList.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -78,18 +78,6 @@ struct Meter_ {
double total; double total;
}; };
extern char* METER_CLASS;
extern MeterType CPUMeter;
extern MeterType ClockMeter;
extern MeterType LoadAverageMeter;
extern MeterType LoadMeter;
extern MeterType MemoryMeter;
extern MeterType SwapMeter;
extern MeterType TasksMeter;
extern MeterType UptimeMeter;
extern MeterType AllCPUsMeter;
typedef enum { typedef enum {
CUSTOM_METERMODE = 0, CUSTOM_METERMODE = 0,
BAR_METERMODE, BAR_METERMODE,
@ -101,8 +89,16 @@ typedef enum {
LAST_METERMODE LAST_METERMODE
} MeterModeId; } MeterModeId;
extern MeterType* Meter_types[];
extern MeterMode* Meter_modes[]; #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"
#ifndef MIN #ifndef MIN
@ -112,15 +108,13 @@ extern MeterMode* Meter_modes[];
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#ifdef DEBUG
extern char* METER_CLASS;
#else
#define METER_CLASS NULL
#ifdef USE_FUNKY_MODES
#endif #endif
extern MeterType* Meter_types[];
Meter* Meter_new(ProcessList* pl, int param, MeterType* type); Meter* Meter_new(ProcessList* pl, int param, MeterType* type);
@ -128,36 +122,28 @@ void Meter_delete(Object* cast);
void Meter_setCaption(Meter* this, char* caption); void Meter_setCaption(Meter* this, char* caption);
void Meter_setMode(Meter* this, int modeIndex); void Meter_setMode(Meter* this, int modeIndex);
ListItem* Meter_toListItem(Meter* this); ListItem* Meter_toListItem(Meter* this);
/* ---------- TextMeterMode ---------- */ /* ---------- TextMeterMode ---------- */
void TextMeterMode_draw(Meter* this, int x, int y, int w);
/* ---------- BarMeterMode ---------- */ /* ---------- BarMeterMode ---------- */
void BarMeterMode_draw(Meter* this, int x, int y, int w);
#ifdef USE_FUNKY_MODES #ifdef USE_FUNKY_MODES
/* ---------- GraphMeterMode ---------- */ /* ---------- GraphMeterMode ---------- */
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0) #define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
void GraphMeterMode_draw(Meter* this, int x, int y, int w);
/* ---------- LEDMeterMode ---------- */ /* ---------- LEDMeterMode ---------- */
#endif
#ifdef USE_FUNKY_MODES
void LEDMeterMode_draw(Meter* this, int x, int y, int w);
#endif #endif
extern MeterMode* Meter_modes[];
#endif #endif

View File

@ -1,105 +0,0 @@
#include "MetersListBox.h"
#include "ListBox.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct MetersListBox_ {
ListBox super;
Settings* settings;
TypedVector* meters;
ScreenManager* scr;
} MetersListBox;
}*/
MetersListBox* MetersListBox_new(Settings* settings, char* header, TypedVector* meters, ScreenManager* scr) {
MetersListBox* this = (MetersListBox*) malloc(sizeof(MetersListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = MetersListBox_delete;
this->settings = settings;
this->meters = meters;
this->scr = scr;
super->eventHandler = MetersListBox_EventHandler;
ListBox_setHeader(super, header);
for (int i = 0; i < TypedVector_size(meters); i++) {
Meter* meter = (Meter*) TypedVector_get(meters, i);
ListBox_add(super, (Object*) Meter_toListItem(meter));
}
return this;
}
void MetersListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
MetersListBox* this = (MetersListBox*) object;
ListBox_done(super);
free(this);
}
HandlerResult MetersListBox_EventHandler(ListBox* super, int ch) {
MetersListBox* this = (MetersListBox*) super;
int selected = ListBox_getSelectedIndex(super);
HandlerResult result = IGNORED;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_F(4):
case 't':
{
Meter* meter = (Meter*) TypedVector_get(this->meters, selected);
int mode = meter->mode + 1;
if (mode == LAST_METERMODE) mode = 1;
Meter_setMode(meter, mode);
ListBox_set(super, selected, (Object*) Meter_toListItem(meter));
result = HANDLED;
break;
}
case KEY_F(7):
case '[':
case '-':
{
TypedVector_moveUp(this->meters, selected);
ListBox_moveSelectedUp(super);
result = HANDLED;
break;
}
case KEY_F(8):
case ']':
case '+':
{
TypedVector_moveDown(this->meters, selected);
ListBox_moveSelectedDown(super);
result = HANDLED;
break;
}
case KEY_F(9):
case KEY_DC:
{
if (selected < TypedVector_size(this->meters)) {
TypedVector_remove(this->meters, selected);
ListBox_remove(super, selected);
}
result = HANDLED;
break;
}
}
if (result == HANDLED) {
Header* header = this->settings->header;
Header_calculateHeight(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}

View File

@ -1,30 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_MetersListBox
#define HEADER_MetersListBox
#include "ListBox.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct MetersListBox_ {
ListBox super;
Settings* settings;
TypedVector* meters;
ScreenManager* scr;
} MetersListBox;
MetersListBox* MetersListBox_new(Settings* settings, char* header, TypedVector* meters, ScreenManager* scr);
void MetersListBox_delete(Object* object);
HandlerResult MetersListBox_EventHandler(ListBox* super, int ch);
#endif

106
MetersPanel.c Normal file
View File

@ -0,0 +1,106 @@
#include "MetersPanel.h"
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
/*{
typedef struct MetersPanel_ {
Panel super;
Settings* settings;
Vector* meters;
ScreenManager* scr;
} MetersPanel;
}*/
static void MetersPanel_delete(Object* object) {
Panel* super = (Panel*) object;
MetersPanel* this = (MetersPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
MetersPanel* this = (MetersPanel*) super;
int selected = Panel_getSelectedIndex(super);
HandlerResult result = IGNORED;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_F(4):
case 't':
{
Meter* meter = (Meter*) Vector_get(this->meters, selected);
int mode = meter->mode + 1;
if (mode == LAST_METERMODE) mode = 1;
Meter_setMode(meter, mode);
Panel_set(super, selected, (Object*) Meter_toListItem(meter));
result = HANDLED;
break;
}
case KEY_F(7):
case '[':
case '-':
{
Vector_moveUp(this->meters, selected);
Panel_moveSelectedUp(super);
result = HANDLED;
break;
}
case KEY_F(8):
case ']':
case '+':
{
Vector_moveDown(this->meters, selected);
Panel_moveSelectedDown(super);
result = HANDLED;
break;
}
case KEY_F(9):
case KEY_DC:
{
if (selected < Vector_size(this->meters)) {
Vector_remove(this->meters, selected);
Panel_remove(super, selected);
}
result = HANDLED;
break;
}
}
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;
}
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;
}

26
MetersPanel.h Normal file
View File

@ -0,0 +1,26 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MetersPanel
#define HEADER_MetersPanel
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct MetersPanel_ {
Panel super;
Settings* settings;
Vector* meters;
ScreenManager* scr;
} MetersPanel;
MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr);
#endif

View File

@ -15,46 +15,43 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
/*{ /*{
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
typedef struct Object_ Object; typedef struct Object_ Object;
typedef void(*Object_Display)(Object*, RichString*); typedef void(*Object_Display)(Object*, RichString*);
typedef int(*Object_Compare)(const Object*, const Object*); typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*); typedef void(*Object_Delete)(Object*);
struct Object_ { struct Object_ {
#ifdef DEBUG
char* class; char* class;
#endif
Object_Display display; Object_Display display;
Object_Compare compare;
Object_Delete delete; Object_Delete delete;
}; };
}*/ }*/
/* private property */ #ifdef DEBUG
char* OBJECT_CLASS = "Object"; char* OBJECT_CLASS = "Object";
void Object_new() { #else
Object* this; #define OBJECT_CLASS NULL
this = malloc(sizeof(Object)); #endif
this->class = OBJECT_CLASS;
this->display = Object_display; #ifdef DEBUG
this->compare = Object_compare;
this->delete = Object_delete; void Object_setClass(void* this, char* class) {
((Object*)this)->class = class;
} }
bool Object_instanceOf(Object* this, char* class) { static void Object_display(Object* this, RichString* out) {
return this->class == class;
}
void Object_delete(Object* this) {
free(this);
}
void Object_display(Object* this, RichString* out) {
char objAddress[50]; char objAddress[50];
sprintf(objAddress, "%s @ %p", this->class, (void*) this); sprintf(objAddress, "%s @ %p", this->class, (void*) this);
RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress); RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress);
} }
int Object_compare(const Object* this, const Object* o) { #endif
return (this - o);
}

View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Object #ifndef HEADER_Object
#define HEADER_Object #define HEADER_Object
@ -17,28 +17,36 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
typedef struct Object_ Object; typedef struct Object_ Object;
typedef void(*Object_Display)(Object*, RichString*); typedef void(*Object_Display)(Object*, RichString*);
typedef int(*Object_Compare)(const Object*, const Object*); typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*); typedef void(*Object_Delete)(Object*);
struct Object_ { struct Object_ {
#ifdef DEBUG
char* class; char* class;
#endif
Object_Display display; Object_Display display;
Object_Compare compare;
Object_Delete delete; Object_Delete delete;
}; };
#ifdef DEBUG
extern char* OBJECT_CLASS;
void Object_new(); #else
#define OBJECT_CLASS NULL
#endif
bool Object_instanceOf(Object* this, char* class); #ifdef DEBUG
void Object_delete(Object* this); void Object_setClass(void* this, char* class);
void Object_display(Object* this, RichString* out); #endif
int Object_compare(const Object* this, const Object* o);
#endif #endif

194
OpenFilesScreen.c Normal file
View File

@ -0,0 +1,194 @@
/*
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.
*/
#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 "OpenFilesScreen.h"
#include "ProcessList.h"
#include "Process.h"
#include "ListItem.h"
#include "Panel.h"
#include "FunctionBar.h"
/*{
typedef struct OpenFiles_ProcessData_ {
char* data[256];
struct OpenFiles_FileData_* files;
bool failed;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
char* data[256];
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ {
Process* process;
Panel* display;
FunctionBar* bar;
bool tracing;
} OpenFilesScreen;
}*/
static char* tbFunctions[] = {"Refresh", "Done ", NULL};
static char* tbKeys[] = {"F5", "Esc"};
static int tbEvents[] = {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, LISTITEM_CLASS, true, ListItem_compare);
this->bar = FunctionBar_new(tbFunctions, tbKeys, tbEvents);
this->tracing = true;
return this;
}
void OpenFilesScreen_delete(OpenFilesScreen* this) {
Panel_delete((Object*)this->display);
FunctionBar_delete((Object*)this->bar);
free(this);
}
static void OpenFilesScreen_draw(OpenFilesScreen* this) {
attrset(CRT_colors[METER_TEXT]);
mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Files open in process %d - %s", this->process->pid, this->process->comm);
attrset(CRT_colors[DEFAULT_COLOR]);
Panel_draw(this->display, true);
FunctionBar_draw(this->bar, NULL);
}
static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(int pid) {
char command[1025];
snprintf(command, 1024, "lsof -p %d -F 2> /dev/null", pid);
FILE* fd = popen(command, "r");
OpenFiles_ProcessData* process = calloc(sizeof(OpenFiles_ProcessData), 1);
OpenFiles_FileData* file = NULL;
OpenFiles_ProcessData* item = process;
process->failed = true;
bool anyRead = false;
while (!feof(fd)) {
int cmd = fgetc(fd);
if (cmd == EOF && !anyRead) {
process->failed = true;
break;
}
anyRead = true;
process->failed = false;
char* entry = malloc(1024);
if (!fgets(entry, 1024, fd)) break;
char* newline = strrchr(entry, '\n');
*newline = '\0';
if (cmd == 'f') {
OpenFiles_FileData* nextFile = calloc(sizeof(OpenFiles_ProcessData), 1);
if (file == NULL) {
process->files = nextFile;
} else {
file->next = nextFile;
}
file = nextFile;
item = (OpenFiles_ProcessData*) file;
}
item->data[cmd] = entry;
}
pclose(fd);
return process;
}
static void OpenFilesScreen_scan(OpenFilesScreen* this) {
Panel* panel = this->display;
int index = MAX(Panel_getSelectedIndex(panel), 0);
Panel_prune(panel);
OpenFiles_ProcessData* process = OpenFilesScreen_getProcessData(this->process->pid);
if (process->failed) {
Panel_add(panel, (Object*) ListItem_new("Could not execute 'lsof'. Please make sure it is available in your $PATH.", 0));
} else {
OpenFiles_FileData* file = process->files;
while (file) {
char entry[1024];
sprintf(entry, "%5s %4s %10s %10s %10s %s",
file->data['f'] ? file->data['f'] : "",
file->data['t'] ? file->data['t'] : "",
file->data['D'] ? file->data['D'] : "",
file->data['s'] ? file->data['s'] : "",
file->data['i'] ? file->data['i'] : "",
file->data['n'] ? file->data['n'] : "");
Panel_add(panel, (Object*) ListItem_new(entry, 0));
for (int i = 0; i < 255; i++)
if (file->data[i])
free(file->data[i]);
OpenFiles_FileData* old = file;
file = file->next;
free(old);
}
for (int i = 0; i < 255; i++)
if (process->data[i])
free(process->data[i]);
}
free(process);
Vector_sort(panel->items);
Panel_setSelected(panel, index);
}
void OpenFilesScreen_run(OpenFilesScreen* this) {
Panel* panel = this->display;
Panel_setHeader(panel, " FD TYPE DEVICE SIZE NODE NAME");
OpenFilesScreen_scan(this);
OpenFilesScreen_draw(this);
//CRT_disableDelay();
bool looping = true;
while (looping) {
Panel_draw(panel, true);
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(this->bar, mevent.x);
}
switch(ch) {
case ERR:
continue;
case KEY_F(5):
clear();
OpenFilesScreen_scan(this);
OpenFilesScreen_draw(this);
break;
case '\014': // Ctrl+L
clear();
OpenFilesScreen_draw(this);
break;
case 'q':
case 27:
looping = false;
break;
case KEY_RESIZE:
Panel_resize(panel, COLS, LINES-2);
OpenFilesScreen_draw(this);
break;
default:
Panel_onKey(panel, ch);
}
}
//CRT_enableDelay();
}

53
OpenFilesScreen.h Normal file
View File

@ -0,0 +1,53 @@
/* 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.
*/
#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 OpenFiles_ProcessData_ {
char* data[256];
struct OpenFiles_FileData_* files;
bool failed;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
char* data[256];
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ {
Process* process;
Panel* display;
FunctionBar* bar;
bool tracing;
} OpenFilesScreen;
OpenFilesScreen* OpenFilesScreen_new(Process* process);
void OpenFilesScreen_delete(OpenFilesScreen* this);
void OpenFilesScreen_run(OpenFilesScreen* this);
#endif

399
Panel.c Normal file
View File

@ -0,0 +1,399 @@
/*
htop - Panel.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 "Object.h"
#include "Panel.h"
#include "Vector.h"
#include "CRT.h"
#include "RichString.h"
#include "ListItem.h"
#include <math.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
/*{
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
#define EVENT_SETSELECTED -1
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
struct Panel_ {
Object super;
int x, y, w, h;
WINDOW* window;
Vector* items;
int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected;
bool needsRedraw;
RichString header;
Panel_EventHandler eventHandler;
};
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
char* PANEL_CLASS = "Panel";
#else
#define PANEL_CLASS NULL
#endif
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
Panel* this;
this = malloc(sizeof(Panel));
Panel_init(this, x, y, w, h, type, owner);
this->items->compare = compare;
return this;
}
void Panel_delete(Object* cast) {
Panel* this = (Panel*)cast;
Panel_done(this);
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;
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->scrollV = 0;
this->scrollH = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
RichString_prune(&(this->header));
if (String_eq(CRT_termType, "linux"))
this->scrollHAmount = 20;
else
this->scrollHAmount = 5;
}
void Panel_done(Panel* this) {
assert (this != NULL);
Vector_delete(this->items);
}
inline void Panel_setRichHeader(Panel* this, RichString header) {
assert (this != NULL);
this->header = header;
this->needsRedraw = true;
}
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;
}
void Panel_move(Panel* this, int x, int y) {
assert (this != NULL);
this->x = x;
this->y = y;
this->needsRedraw = true;
}
void Panel_resize(Panel* this, int w, int h) {
assert (this != NULL);
if (this->header.len > 0)
h--;
this->w = w;
this->h = h;
this->needsRedraw = true;
}
void Panel_prune(Panel* this) {
assert (this != NULL);
Vector_prune(this->items);
this->scrollV = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
}
void Panel_add(Panel* this, Object* o) {
assert (this != NULL);
Vector_add(this->items, o);
this->needsRedraw = true;
}
void Panel_insert(Panel* this, int i, Object* o) {
assert (this != NULL);
Vector_insert(this->items, i, o);
this->needsRedraw = true;
}
void Panel_set(Panel* this, int i, Object* o) {
assert (this != NULL);
Vector_set(this->items, i, o);
}
Object* Panel_get(Panel* this, int i) {
assert (this != NULL);
return Vector_get(this->items, i);
}
Object* Panel_remove(Panel* this, int i) {
assert (this != NULL);
this->needsRedraw = true;
Object* removed = Vector_remove(this->items, i);
if (this->selected > 0 && this->selected >= Vector_size(this->items))
this->selected--;
return removed;
}
Object* Panel_getSelected(Panel* this) {
assert (this != NULL);
return Vector_get(this->items, this->selected);
}
void Panel_moveSelectedUp(Panel* this) {
assert (this != NULL);
Vector_moveUp(this->items, this->selected);
if (this->selected > 0)
this->selected--;
}
void Panel_moveSelectedDown(Panel* this) {
assert (this != NULL);
Vector_moveDown(this->items, this->selected);
if (this->selected + 1 < Vector_size(this->items))
this->selected++;
}
int Panel_getSelectedIndex(Panel* this) {
assert (this != NULL);
return this->selected;
}
int Panel_size(Panel* this) {
assert (this != NULL);
return Vector_size(this->items);
}
void Panel_setSelected(Panel* this, int selected) {
assert (this != NULL);
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
this->selected = selected;
if (this->eventHandler) {
this->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);
}
if (this->selected < first) {
first = this->selected;
this->scrollV = first;
this->needsRedraw = true;
}
if (this->selected >= last) {
last = MIN(itemCount, this->selected + 1);
first = MAX(0, last - this->h);
this->scrollV = first;
this->needsRedraw = true;
}
assert(first >= 0);
assert(last <= itemCount);
if (this->header.len > 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) {
RichString_printoffnVal(this->header, y, x, scrollH,
MIN(this->header.len - scrollH, this->w));
}
attrset(CRT_colors[RESET_COLOR]);
y++;
}
int highlight = focus
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
if (this->needsRedraw) {
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) {
attrset(highlight);
RichString_setAttr(&itemRef, highlight);
mvhline(y + j, x+0, ' ', this->w);
if (amt > 0)
RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
attrset(CRT_colors[RESET_COLOR]);
} else {
mvhline(y+j, x+0, ' ', this->w);
if (amt > 0)
RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
}
}
for (int i = y + (last - first); i < y + this->h; i++)
mvhline(i, x+0, ' ', this->w);
this->needsRedraw = false;
} else {
Object* oldObj = Vector_get(this->items, this->oldSelected);
RichString oldRef;
RichString_initVal(oldRef);
oldObj->display(oldObj, &oldRef);
Object* newObj = Vector_get(this->items, this->selected);
RichString newRef;
RichString_initVal(newRef);
newObj->display(newObj, &newRef);
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
if (scrollH < oldRef.len)
RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
this->scrollH, MIN(oldRef.len - scrollH, this->w));
attrset(highlight);
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
RichString_setAttr(&newRef, highlight);
if (scrollH < newRef.len)
RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
this->scrollH, MIN(newRef.len - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]);
}
this->oldSelected = this->selected;
move(0, 0);
}
bool Panel_onKey(Panel* this, int key) {
assert (this != NULL);
switch (key) {
case KEY_DOWN:
if (this->selected + 1 < Vector_size(this->items))
this->selected++;
return true;
case KEY_UP:
if (this->selected > 0)
this->selected--;
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;
}
}
return true;
#endif
#ifdef KEY_C_UP
case KEY_C_UP:
if (this->selected > 0) {
this->selected--;
if (this->scrollV > 0) {
this->scrollV--;
this->needsRedraw = true;
}
}
return true;
#endif
case KEY_LEFT:
if (this->scrollH > 0) {
this->scrollH -= 5;
this->needsRedraw = true;
}
return true;
case KEY_RIGHT:
this->scrollH += 5;
this->needsRedraw = true;
return true;
case KEY_PPAGE:
this->selected -= (this->h - 1);
this->scrollV -= (this->h - 1);
if (this->selected < 0)
this->selected = 0;
if (this->scrollV < 0)
this->scrollV = 0;
this->needsRedraw = true;
return true;
case KEY_NPAGE:
this->selected += (this->h - 1);
int size = Vector_size(this->items);
if (this->selected >= size)
this->selected = size - 1;
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;
return true;
case KEY_END:
this->selected = Vector_size(this->items) - 1;
return true;
}
return false;
}

115
Panel.h Normal file
View File

@ -0,0 +1,115 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Panel
#define HEADER_Panel
/*
htop - Panel.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 "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
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
#define EVENT_SETSELECTED -1
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
struct Panel_ {
Object super;
int x, y, w, h;
WINDOW* window;
Vector* items;
int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected;
bool needsRedraw;
RichString header;
Panel_EventHandler eventHandler;
};
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
extern char* PANEL_CLASS;
#else
#define PANEL_CLASS NULL
#endif
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare);
void Panel_delete(Object* cast);
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner);
void Panel_done(Panel* this);
extern void Panel_setRichHeader(Panel* this, RichString header);
extern void Panel_setHeader(Panel* this, char* header);
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh);
void Panel_move(Panel* this, int x, int y);
void Panel_resize(Panel* this, int w, int h);
void Panel_prune(Panel* this);
void Panel_add(Panel* this, Object* o);
void Panel_insert(Panel* this, int i, Object* o);
void Panel_set(Panel* this, int i, Object* o);
Object* Panel_get(Panel* this, int i);
Object* Panel_remove(Panel* this, int i);
Object* Panel_getSelected(Panel* this);
void Panel_moveSelectedUp(Panel* this);
void Panel_moveSelectedDown(Panel* this);
int Panel_getSelectedIndex(Panel* this);
int Panel_size(Panel* this);
void Panel_setSelected(Panel* this, int selected);
void Panel_draw(Panel* this, bool focus);
bool Panel_onKey(Panel* this, int key);
#endif

534
Process.c
View File

@ -11,6 +11,7 @@ in the source distribution for its full text.
#include "CRT.h" #include "CRT.h"
#include "String.h" #include "String.h"
#include "Process.h" #include "Process.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
@ -25,13 +26,20 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <pwd.h> #include <pwd.h>
#include <sched.h>
#ifdef HAVE_PLPA
#include <plpa.h>
#endif
// This works only with glibc 2.1+. On earlier versions // This works only with glibc 2.1+. On earlier versions
// the behavior is similar to have a hardcoded page size. // the behavior is similar to have a hardcoded page size.
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) / 1024 ) #ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
#define PROCESS_COMM_LEN 300 #define PROCESS_COMM_LEN 300
#define PROCESS_USER_LEN 10
/*{ /*{
@ -40,7 +48,17 @@ typedef enum ProcessField_ {
STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE, STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE,
STARTSTACK, KSTKESP, KSTKEIP, SIGNAL, BLOCKED, SSIGIGNORE, SIGCATCH, WCHAN, NSWAP, CNSWAP, EXIT_SIGNAL, 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, PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
USER, TIME, 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
LAST_PROCESSFIELD
} ProcessField; } ProcessField;
struct ProcessList_; struct ProcessList_;
@ -51,27 +69,32 @@ typedef struct Process_ {
struct ProcessList_ *pl; struct ProcessList_ *pl;
bool updated; bool updated;
int pid; unsigned int pid;
char* comm; char* comm;
int indent; int indent;
char state; char state;
bool tag; bool tag;
int ppid; unsigned int ppid;
int pgrp; unsigned int pgrp;
int session; unsigned int session;
int tty_nr; unsigned int tty_nr;
unsigned int tgid;
int tpgid; int tpgid;
unsigned long int flags; unsigned long int flags;
#ifdef DEBUG
unsigned long int minflt; unsigned long int minflt;
unsigned long int cminflt; unsigned long int cminflt;
unsigned long int majflt; unsigned long int majflt;
unsigned long int cmajflt; unsigned long int cmajflt;
#endif
unsigned long int utime; unsigned long int utime;
unsigned long int stime; unsigned long int stime;
long int cutime; long int cutime;
long int cstime; long int cstime;
long int priority; long int priority;
long int nice; long int nice;
long int nlwp;
#ifdef DEBUG
long int itrealvalue; long int itrealvalue;
unsigned long int starttime; unsigned long int starttime;
unsigned long int vsize; unsigned long int vsize;
@ -89,6 +112,7 @@ typedef struct Process_ {
unsigned long int wchan; unsigned long int wchan;
unsigned long int nswap; unsigned long int nswap;
unsigned long int cnswap; unsigned long int cnswap;
#endif
int exit_signal; int exit_signal;
int processor; int processor;
int m_size; int m_size;
@ -101,111 +125,112 @@ typedef struct Process_ {
uid_t st_uid; uid_t st_uid;
float percent_cpu; float percent_cpu;
float percent_mem; float percent_mem;
char user[PROCESS_USER_LEN + 1]; char* user;
#ifdef HAVE_OPENVZ
unsigned int ctid;
unsigned int vpid;
#endif
#ifdef HAVE_VSERVER
unsigned int vxid;
#endif
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
} Process; } Process;
extern char* PROCESS_CLASS;
extern char* Process_fieldNames[];
}*/ }*/
/* private property */ #ifdef DEBUG
char* PROCESS_CLASS = "Process"; char* PROCESS_CLASS = "Process";
#else
#define PROCESS_CLASS NULL
#endif
/* private property */ char *Process_fieldNames[] = {
char *Process_fieldNames[] = { "", "PID", "Command", "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", "SIGIGNORE", "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", "*** report bug! ***"}; "", "PID", "Command", "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", "SIGIGNORE", "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", "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
"*** report bug! ***"
};
Process* Process_new(struct ProcessList_ *pl) { char *Process_fieldTitles[] = {
Process* this = malloc(sizeof(Process)); "", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ",
((Object*)this)->class = PROCESS_CLASS; " TTY ", "TPGID ", "- ", "- ", "- ", "- ", "- ",
((Object*)this)->display = Process_display; " UTIME+ ", " STIME+ ", "- ", "- ", "PRI ", " NI ", "- ",
((Object*)this)->compare = Process_compare; "- ", "- ", "- ", "- ", "- ", "- ", "- ",
((Object*)this)->delete = Process_delete; "- ", "- ", "- ", "- ", "- ", "- ", "- ",
this->pl = pl; "- ", "- ", "- ", "CPU ", " VIRT ", " RES ", " SHR ",
this->tag = false; " CODE ", " DATA ", " LIB ", " DIRTY ", " UID ", "CPU% ", "MEM% ",
this->updated = false; "USER ", " TIME+ ", "NLWP ", " TGID ",
this->utime = 0; #ifdef HAVE_OPENVZ
this->stime = 0; " CTID ", " VPID ",
this->comm = NULL; #endif
return this; #ifdef HAVE_VSERVER
} " VXID ",
#endif
#ifdef HAVE_TASKSTATS
" RD_CHAR ", " WR_CHAR ", " RD_SYSC ", " WR_SYSC ", " IO_RD ", " IO_WR ", " IO_CANCEL ",
" IORR ", " IOWR ", " IO ",
#endif
};
Process* Process_clone(Process* this) { static int Process_getuid = -1;
Process* clone = malloc(sizeof(Process));
memcpy(clone, this, sizeof(Process));
return clone;
}
void Process_delete(Object* cast) {
Process* this = (Process*) cast;
if (this->comm) free(this->comm);
assert (this != NULL);
free(this);
}
void Process_display(Object* cast, RichString* out) {
Process* this = (Process*) cast;
ProcessField* fields = this->pl->fields;
RichString_prune(out);
for (int i = 0; fields[i]; i++)
Process_writeField(this, out, fields[i]);
if (this->pl->shadowOtherUsers && this->st_uid != getuid())
RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
if (this->tag == true)
RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
assert(out->len > 0);
}
void Process_toggleTag(Process* this) {
this->tag = this->tag == true ? false : true;
}
void Process_setPriority(Process* this, int priority) {
int old_prio = getpriority(PRIO_PROCESS, this->pid);
int err = setpriority(PRIO_PROCESS, this->pid, priority);
if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) {
this->nice = priority;
}
}
void Process_sendSignal(Process* this, int signal) {
kill(this->pid, signal);
}
#define ONE_K 1024 #define ONE_K 1024
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K) #define ONE_G (ONE_M * ONE_K)
/* private */ static void Process_printLargeNumber(Process* this, RichString *str, unsigned long number) {
void Process_printLargeNumber(Process* this, RichString *str, unsigned int number) {
char buffer[11]; char buffer[11];
int len; int len;
if(number >= (1000 * ONE_M)) { if(number >= (10 * ONE_M)) {
len = snprintf(buffer, 10, "%4.2fG ", (float)number / ONE_M); len = snprintf(buffer, 10, "%3.1fG ", (float)number / ONE_M);
RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len); RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len);
} else if(number >= (100000)) { } else if(number >= (100000)) {
len = snprintf(buffer, 10, "%4dM ", number / ONE_K); len = snprintf(buffer, 10, "%4ldM ", number / ONE_K);
int attr = this->pl->highlightMegabytes int attr = this->pl->highlightMegabytes
? CRT_colors[PROCESS_MEGABYTES] ? CRT_colors[PROCESS_MEGABYTES]
: CRT_colors[PROCESS]; : CRT_colors[PROCESS];
RichString_appendn(str, attr, buffer, len); RichString_appendn(str, attr, buffer, len);
} else if (this->pl->highlightMegabytes && number >= 1000) { } else if (this->pl->highlightMegabytes && number >= 1000) {
len = snprintf(buffer, 10, "%2d", number/1000); len = snprintf(buffer, 10, "%2ld", number/1000);
RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer, len); RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer, len);
number %= 1000; number %= 1000;
len = snprintf(buffer, 10, "%03d ", number); len = snprintf(buffer, 10, "%03ld ", number);
RichString_appendn(str, CRT_colors[PROCESS], buffer, len); RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
} else { } else {
len = snprintf(buffer, 10, "%5d ", number); len = snprintf(buffer, 10, "%5ld ", number);
RichString_appendn(str, CRT_colors[PROCESS], buffer, len); RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
} }
} }
/* private property */ static double jiffy = 0.0;
double jiffy = 0.0;
/* private */
static void Process_printTime(RichString* str, unsigned long t) { static void Process_printTime(RichString* str, unsigned long t) {
if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK); if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
double jiffytime = 1.0 / jiffy; double jiffytime = 1.0 / jiffy;
@ -228,44 +253,62 @@ static void Process_printTime(RichString* str, unsigned long t) {
RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer); RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer);
} }
/* private */ static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
inline static void Process_writeCommand(Process* this, int attr, RichString* str) { int start = str->len;
if (this->pl->highlightBaseName) {
char* firstSpace = strchr(this->comm, ' ');
if (firstSpace) {
char* slash = firstSpace;
while (slash > this->comm && *slash != '/')
slash--;
if (slash > this->comm) {
slash++;
RichString_appendn(str, attr, this->comm, slash - this->comm);
}
RichString_appendn(str, CRT_colors[PROCESS_BASENAME], slash, firstSpace - slash);
RichString_append(str, attr, firstSpace);
} else {
RichString_append(str, CRT_colors[PROCESS_BASENAME], this->comm);
}
} else {
RichString_append(str, attr, this->comm); RichString_append(str, attr, this->comm);
if (this->pl->highlightBaseName) {
int finish = str->len - 1;
int space = RichString_findChar(str, ' ', start);
if (space != -1)
finish = space - 1;
for (;;) {
int slash = RichString_findChar(str, '/', start);
if (slash == -1 || slash > finish)
break;
start = slash + 1;
}
RichString_setAttrn(str, baseattr, start, finish);
} }
} }
void Process_writeField(Process* this, RichString* str, ProcessField field) { static inline void Process_outputRate(Process* this, RichString* str, int attr, char* buffer, int n, double rate) {
rate = rate / 1024;
if (rate < 0.01)
snprintf(buffer, n, " 0 ");
else if (rate <= 10)
snprintf(buffer, n, "%5.2f ", rate);
else if (rate <= 100)
snprintf(buffer, n, "%5.1f ", rate);
else {
Process_printLargeNumber(this, str, rate);
return;
}
RichString_append(str, attr, buffer);
}
static void Process_writeField(Process* this, RichString* str, ProcessField field) {
char buffer[PROCESS_COMM_LEN]; char buffer[PROCESS_COMM_LEN];
int attr = CRT_colors[DEFAULT_COLOR]; int attr = CRT_colors[DEFAULT_COLOR];
int baseattr = CRT_colors[PROCESS_BASENAME];
int n = PROCESS_COMM_LEN; int n = PROCESS_COMM_LEN;
switch (field) { switch (field) {
case PID: snprintf(buffer, n, "%5d ", this->pid); break; case PID: snprintf(buffer, n, "%5u ", this->pid); break;
case PPID: snprintf(buffer, n, "%5d ", this->ppid); break; case PPID: snprintf(buffer, n, "%5u ", this->ppid); break;
case PGRP: snprintf(buffer, n, "%5d ", this->pgrp); break; case PGRP: snprintf(buffer, n, "%5u ", this->pgrp); break;
case SESSION: snprintf(buffer, n, "%5d ", this->session); break; case SESSION: snprintf(buffer, n, "%5u ", this->session); break;
case TTY_NR: snprintf(buffer, n, "%5d ", this->tty_nr); break; case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break;
case TGID: snprintf(buffer, n, "%5u ", this->tgid); break;
case TPGID: snprintf(buffer, n, "%5d ", this->tpgid); break; case TPGID: snprintf(buffer, n, "%5d ", this->tpgid); break;
case PROCESSOR: snprintf(buffer, n, "%3d ", this->processor+1); break; case PROCESSOR: snprintf(buffer, n, "%3d ", this->processor+1); break;
case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break;
case COMM: { case COMM: {
if (this->pl->highlightThreads && (this->pid != this->tgid || this->m_size == 0)) {
attr = CRT_colors[PROCESS_THREAD];
baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
}
if (!this->pl->treeView || this->indent == 0) { if (!this->pl->treeView || this->indent == 0) {
Process_writeCommand(this, attr, str); Process_writeCommand(this, attr, baseattr, str);
return; return;
} else { } else {
char* buf = buffer; char* buf = buffer;
@ -286,7 +329,7 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
else else
snprintf(buf, n, " ,- "); snprintf(buf, n, " ,- ");
RichString_append(str, CRT_colors[PROCESS_TREE], buffer); RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
Process_writeCommand(this, attr, str); Process_writeCommand(this, attr, baseattr, str);
return; return;
} }
} }
@ -311,14 +354,22 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
: attr; : attr;
break; break;
} }
case M_SIZE: Process_printLargeNumber(this, str, this->m_size * PAGE_SIZE); return; case M_DRS: Process_printLargeNumber(this, str, this->m_drs * PAGE_SIZE_KB); return;
case M_RESIDENT: Process_printLargeNumber(this, str, this->m_resident * PAGE_SIZE); return; case M_DT: Process_printLargeNumber(this, str, this->m_dt * PAGE_SIZE_KB); return;
case M_SHARE: Process_printLargeNumber(this, str, this->m_share * PAGE_SIZE); return; case M_LRS: Process_printLargeNumber(this, str, this->m_lrs * PAGE_SIZE_KB); return;
case M_TRS: Process_printLargeNumber(this, str, this->m_trs * PAGE_SIZE_KB); return;
case M_SIZE: Process_printLargeNumber(this, str, this->m_size * PAGE_SIZE_KB); return;
case M_RESIDENT: Process_printLargeNumber(this, str, this->m_resident * PAGE_SIZE_KB); return;
case M_SHARE: Process_printLargeNumber(this, str, this->m_share * PAGE_SIZE_KB); return;
case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break; case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break;
case USER: { case USER: {
if (getuid() != this->st_uid) if (Process_getuid != this->st_uid)
attr = CRT_colors[PROCESS_SHADOW]; attr = CRT_colors[PROCESS_SHADOW];
if (this->user) {
snprintf(buffer, n, "%-8s ", this->user); snprintf(buffer, n, "%-8s ", this->user);
} else {
snprintf(buffer, n, "%-8d ", this->st_uid);
}
if (buffer[8] != '\0') { if (buffer[8] != '\0') {
buffer[8] = ' '; buffer[8] = ' ';
buffer[9] = '\0'; buffer[9] = '\0';
@ -331,8 +382,10 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
case CSTIME: Process_printTime(str, this->cstime); return; case CSTIME: Process_printTime(str, this->cstime); return;
case TIME: Process_printTime(str, this->utime + this->stime); return; case TIME: Process_printTime(str, this->utime + this->stime); return;
case PERCENT_CPU: { case PERCENT_CPU: {
if (this->percent_cpu > 99.9) { if (this->percent_cpu > 999.9) {
snprintf(buffer, n, "100. "); snprintf(buffer, n, "%4d ", (unsigned int)this->percent_cpu);
} else if (this->percent_cpu > 99.9) {
snprintf(buffer, n, "%3d. ", (unsigned int)this->percent_cpu);
} else { } else {
snprintf(buffer, n, "%4.1f ", this->percent_cpu); snprintf(buffer, n, "%4.1f ", this->percent_cpu);
} }
@ -346,76 +399,207 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
} }
break; break;
} }
#ifdef HAVE_OPENVZ
case CTID: snprintf(buffer, n, "%5u ", this->ctid); break;
case VPID: snprintf(buffer, n, "%5u ", this->vpid); break;
#endif
#ifdef HAVE_VSERVER
case VXID: snprintf(buffer, n, "%5u ", this->vxid); break;
#endif
#ifdef HAVE_TASKSTATS
case RCHAR: snprintf(buffer, n, "%10llu ", this->io_rchar); break;
case WCHAR: snprintf(buffer, n, "%10llu ", this->io_wchar); break;
case SYSCR: snprintf(buffer, n, "%10llu ", this->io_syscr); break;
case SYSCW: snprintf(buffer, n, "%10llu ", this->io_syscw); break;
case RBYTES: snprintf(buffer, n, "%10llu ", this->io_read_bytes); break;
case WBYTES: snprintf(buffer, n, "%10llu ", this->io_write_bytes); break;
case CNCLWB: snprintf(buffer, n, "%10llu ", this->io_cancelled_write_bytes); break;
case IO_READ_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps); return;
case IO_WRITE_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_write_bps); return;
case IO_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps + this->io_rate_write_bps); return;
#endif
default: default:
snprintf(buffer, n, "- "); snprintf(buffer, n, "- ");
} }
RichString_append(str, attr, buffer); RichString_append(str, attr, buffer);
return;
} }
int Process_compare(const Object* v1, const Object* v2) { static void Process_display(Object* cast, RichString* out) {
Process* this = (Process*) cast;
ProcessField* fields = this->pl->fields;
RichString_init(out);
for (int i = 0; fields[i]; i++)
Process_writeField(this, out, fields[i]);
if (this->pl->shadowOtherUsers && this->st_uid != Process_getuid)
RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
if (this->tag == true)
RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
assert(out->len > 0);
}
void Process_delete(Object* cast) {
Process* this = (Process*) cast;
assert (this != NULL);
if (this->comm) free(this->comm);
free(this);
}
Process* Process_new(struct ProcessList_ *pl) {
Process* this = calloc(sizeof(Process), 1);
Object_setClass(this, PROCESS_CLASS);
((Object*)this)->display = Process_display;
((Object*)this)->delete = Process_delete;
this->pid = 0;
this->pl = pl;
this->tag = false;
this->updated = false;
this->utime = 0;
this->stime = 0;
this->comm = NULL;
this->indent = 0;
if (Process_getuid == -1) Process_getuid = getuid();
return this;
}
Process* Process_clone(Process* this) {
Process* clone = malloc(sizeof(Process));
#if HAVE_TASKSTATS
this->io_rchar = 0;
this->io_wchar = 0;
this->io_syscr = 0;
this->io_syscw = 0;
this->io_read_bytes = 0;
this->io_rate_read_bps = 0;
this->io_rate_read_time = 0;
this->io_write_bytes = 0;
this->io_rate_write_bps = 0;
this->io_rate_write_time = 0;
this->io_cancelled_write_bytes = 0;
#endif
memcpy(clone, this, sizeof(Process));
this->comm = NULL;
this->pid = 0;
return clone;
}
void Process_toggleTag(Process* this) {
this->tag = this->tag == true ? false : true;
}
bool Process_setPriority(Process* this, int priority) {
int old_prio = getpriority(PRIO_PROCESS, this->pid);
int err = setpriority(PRIO_PROCESS, this->pid, priority);
if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) {
this->nice = priority;
}
return (err == 0);
}
#ifdef HAVE_PLPA
unsigned long Process_getAffinity(Process* this) {
unsigned long mask = 0;
plpa_sched_getaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask);
return mask;
}
bool Process_setAffinity(Process* this, unsigned long mask) {
return (plpa_sched_setaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask) == 0);
}
#endif
void Process_sendSignal(Process* this, int signal) {
kill(this->pid, signal);
}
int Process_pidCompare(const void* v1, const void* v2) {
Process* p1 = (Process*)v1; Process* p1 = (Process*)v1;
Process* p2 = (Process*)v2; Process* p2 = (Process*)v2;
int direction = p1->pl->direction; return (p1->pid - p2->pid);
switch (p1->pl->sortKey) {
case PID:
return (p2->pid - p1->pid) * direction;
case PPID:
return (p2->ppid - p1->ppid) * direction;
case USER:
return strcmp(p2->user, p1->user) * direction;
case PRIORITY:
return (p2->priority - p1->priority) * direction;
case STATE:
return (p2->state - p1->state) * direction;
case NICE:
return (p2->nice - p1->nice) * direction;
case M_SIZE:
return (p1->m_size - p2->m_size) * direction;
case M_RESIDENT:
return (p1->m_resident - p2->m_resident) * direction;
case M_SHARE:
return (p1->m_share - p2->m_share) * direction;
case PERCENT_CPU:
return (p1->percent_cpu < p2->percent_cpu ? -1 : 1) * direction;
case PERCENT_MEM:
return (p1->percent_mem < p2->percent_mem ? -1 : 1) * direction;
case UTIME:
return (p1->utime - p2->utime) * direction;
case STIME:
return (p1->stime - p2->stime) * direction;
case TIME:
return ((p1->utime+p1->stime) - (p2->utime+p2->stime)) * direction;
case COMM:
return strcmp(p2->comm, p1->comm) * direction;
default:
return (p2->pid - p1->pid) * direction;
}
} }
char* Process_printField(ProcessField field) { int Process_compare(const void* v1, const void* v2) {
switch (field) { Process *p1, *p2;
case PID: return " PID "; ProcessList *pl = ((Process*)v1)->pl;
case PPID: return " PPID "; if (pl->direction == 1) {
case PGRP: return " PGRP "; p1 = (Process*)v1;
case SESSION: return " SESN "; p2 = (Process*)v2;
case TTY_NR: return " TTY "; } else {
case TPGID: return " TGID "; p2 = (Process*)v1;
case COMM: return "Command "; p1 = (Process*)v2;
case STATE: return "S ";
case PRIORITY: return "PRI ";
case NICE: return " NI ";
case M_SIZE: return " VIRT ";
case M_RESIDENT: return " RES ";
case M_SHARE: return " SHR ";
case ST_UID: return " UID ";
case USER: return "USER ";
case UTIME: return " UTIME+ ";
case STIME: return " STIME+ ";
case TIME: return " TIME+ ";
case PERCENT_CPU: return "CPU% ";
case PERCENT_MEM: return "MEM% ";
case PROCESSOR: return "CPU ";
default: return "- ";
} }
long long diff;
switch (pl->sortKey) {
case PID:
return (p1->pid - p2->pid);
case PPID:
return (p1->ppid - p2->ppid);
case USER:
return strcmp(p1->user ? p1->user : "", p2->user ? p2->user : "");
case PRIORITY:
return (p1->priority - p2->priority);
case PROCESSOR:
return (p1->processor - p2->processor);
case SESSION:
return (p1->session - p2->session);
case STATE:
return (p1->state - p2->state);
case NICE:
return (p1->nice - p2->nice);
case M_DRS:
return (p2->m_drs - p1->m_drs);
case M_DT:
return (p2->m_dt - p1->m_dt);
case M_LRS:
return (p2->m_lrs - p1->m_lrs);
case M_TRS:
return (p2->m_trs - p1->m_trs);
case M_SIZE:
return (p2->m_size - p1->m_size);
case M_RESIDENT:
return (p2->m_resident - p1->m_resident);
case M_SHARE:
return (p2->m_share - p1->m_share);
case PERCENT_CPU:
return (p2->percent_cpu > p1->percent_cpu ? 1 : -1);
case PERCENT_MEM:
return (p2->m_resident - p1->m_resident);
case UTIME:
return (p2->utime - p1->utime);
case STIME:
return (p2->stime - p1->stime);
case TIME:
return ((p2->utime+p2->stime) - (p1->utime+p1->stime));
case COMM:
return strcmp(p1->comm, p2->comm);
case NLWP:
return (p1->nlwp - p2->nlwp);
#ifdef HAVE_OPENVZ
case CTID:
return (p1->ctid - p2->ctid);
case VPID:
return (p1->vpid - p2->vpid);
#endif
#ifdef HAVE_VSERVER
case VXID:
return (p1->vxid - p2->vxid);
#endif
#ifdef HAVE_TASKSTATS
case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff;
case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff;
case SYSCR: diff = p2->io_syscr - p1->io_syscr; goto test_diff;
case SYSCW: diff = p2->io_syscw - p1->io_syscw; goto test_diff;
case RBYTES: diff = p2->io_read_bytes - p1->io_read_bytes; goto test_diff;
case WBYTES: diff = p2->io_write_bytes - p1->io_write_bytes; goto test_diff;
case CNCLWB: diff = p2->io_cancelled_write_bytes - p1->io_cancelled_write_bytes; goto test_diff;
case IO_READ_RATE: diff = p2->io_rate_read_bps - p1->io_rate_read_bps; goto test_diff;
case IO_WRITE_RATE: diff = p2->io_rate_write_bps - p1->io_rate_write_bps; goto test_diff;
case IO_RATE: diff = (p2->io_rate_read_bps + p2->io_rate_write_bps) - (p1->io_rate_read_bps + p1->io_rate_write_bps); goto test_diff;
#endif
default:
return (p1->pid - p2->pid);
}
test_diff:
return (diff > 0) ? 1 : (diff < 0 ? -1 : 0);
} }

110
Process.h
View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Process #ifndef HEADER_Process
#define HEADER_Process #define HEADER_Process
@ -14,6 +14,7 @@ in the source distribution for its full text.
#include "Object.h" #include "Object.h"
#include "CRT.h" #include "CRT.h"
#include "String.h" #include "String.h"
#include "RichString.h"
#include "debug.h" #include "debug.h"
@ -28,13 +29,20 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <pwd.h> #include <pwd.h>
#include <sched.h>
#ifdef HAVE_PLPA
#include <plpa.h>
#endif
// This works only with glibc 2.1+. On earlier versions // This works only with glibc 2.1+. On earlier versions
// the behavior is similar to have a hardcoded page size. // the behavior is similar to have a hardcoded page size.
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) / 1024 ) #ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
#define PROCESS_COMM_LEN 300 #define PROCESS_COMM_LEN 300
#define PROCESS_USER_LEN 10
typedef enum ProcessField_ { typedef enum ProcessField_ {
@ -42,7 +50,17 @@ typedef enum ProcessField_ {
STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE, STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE,
STARTSTACK, KSTKESP, KSTKEIP, SIGNAL, BLOCKED, SSIGIGNORE, SIGCATCH, WCHAN, NSWAP, CNSWAP, EXIT_SIGNAL, 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, PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
USER, TIME, 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
LAST_PROCESSFIELD
} ProcessField; } ProcessField;
struct ProcessList_; struct ProcessList_;
@ -53,27 +71,32 @@ typedef struct Process_ {
struct ProcessList_ *pl; struct ProcessList_ *pl;
bool updated; bool updated;
int pid; unsigned int pid;
char* comm; char* comm;
int indent; int indent;
char state; char state;
bool tag; bool tag;
int ppid; unsigned int ppid;
int pgrp; unsigned int pgrp;
int session; unsigned int session;
int tty_nr; unsigned int tty_nr;
unsigned int tgid;
int tpgid; int tpgid;
unsigned long int flags; unsigned long int flags;
#ifdef DEBUG
unsigned long int minflt; unsigned long int minflt;
unsigned long int cminflt; unsigned long int cminflt;
unsigned long int majflt; unsigned long int majflt;
unsigned long int cmajflt; unsigned long int cmajflt;
#endif
unsigned long int utime; unsigned long int utime;
unsigned long int stime; unsigned long int stime;
long int cutime; long int cutime;
long int cstime; long int cstime;
long int priority; long int priority;
long int nice; long int nice;
long int nlwp;
#ifdef DEBUG
long int itrealvalue; long int itrealvalue;
unsigned long int starttime; unsigned long int starttime;
unsigned long int vsize; unsigned long int vsize;
@ -91,6 +114,7 @@ typedef struct Process_ {
unsigned long int wchan; unsigned long int wchan;
unsigned long int nswap; unsigned long int nswap;
unsigned long int cnswap; unsigned long int cnswap;
#endif
int exit_signal; int exit_signal;
int processor; int processor;
int m_size; int m_size;
@ -103,38 +127,64 @@ typedef struct Process_ {
uid_t st_uid; uid_t st_uid;
float percent_cpu; float percent_cpu;
float percent_mem; float percent_mem;
char user[PROCESS_USER_LEN + 1]; char* user;
#ifdef HAVE_OPENVZ
unsigned int ctid;
unsigned int vpid;
#endif
#ifdef HAVE_VSERVER
unsigned int vxid;
#endif
#ifdef HAVE_TASKSTATS
unsigned long long io_rchar;
unsigned long long io_wchar;
unsigned long long io_syscr;
unsigned long long io_syscw;
unsigned long long io_read_bytes;
unsigned long long io_write_bytes;
unsigned long long io_cancelled_write_bytes;
double io_rate_read_bps;
unsigned long long io_rate_read_time;
double io_rate_write_bps;
unsigned long long io_rate_write_time;
#endif
} Process; } Process;
#ifdef DEBUG
extern char* PROCESS_CLASS; extern char* PROCESS_CLASS;
#else
#define PROCESS_CLASS NULL
#endif
extern char* Process_fieldNames[]; extern char *Process_fieldNames[];
extern char *Process_fieldTitles[];
Process* Process_new(struct ProcessList_ *pl);
Process* Process_clone(Process* this);
void Process_delete(Object* cast);
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 1024
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K) #define ONE_G (ONE_M * ONE_K)
void Process_writeField(Process* this, RichString* str, ProcessField field); void Process_delete(Object* cast);
int Process_compare(const Object* v1, const Object* v2); Process* Process_new(struct ProcessList_ *pl);
char* Process_printField(ProcessField field); Process* Process_clone(Process* this);
void Process_toggleTag(Process* this);
bool Process_setPriority(Process* this, int priority);
#ifdef HAVE_PLPA
unsigned long Process_getAffinity(Process* this);
bool Process_setAffinity(Process* this, unsigned long mask);
#endif
void Process_sendSignal(Process* this, int signal);
int Process_pidCompare(const void* v1, const void* v2);
int Process_compare(const void* v1, const void* v2);
#endif #endif

View File

@ -12,9 +12,10 @@ in the source distribution for its full text.
#include "ProcessList.h" #include "ProcessList.h"
#include "Process.h" #include "Process.h"
#include "TypedVector.h" #include "Vector.h"
#include "UsersTable.h" #include "UsersTable.h"
#include "Hashtable.h" #include "Hashtable.h"
#include "String.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -36,11 +37,11 @@ in the source distribution for its full text.
#endif #endif
#ifndef PROCSTATFILE #ifndef PROCSTATFILE
#define PROCSTATFILE "/proc/stat" #define PROCSTATFILE PROCDIR "/stat"
#endif #endif
#ifndef PROCMEMINFOFILE #ifndef PROCMEMINFOFILE
#define PROCMEMINFOFILE "/proc/meminfo" #define PROCMEMINFOFILE PROCDIR "/meminfo"
#endif #endif
#ifndef MAX_NAME #ifndef MAX_NAME
@ -48,16 +49,24 @@ in the source distribution for its full text.
#endif #endif
#ifndef MAX_READ #ifndef MAX_READ
#define MAX_READ 8192 #define MAX_READ 2048
#endif
#ifndef PER_PROCESSOR_FIELDS
#define PER_PROCESSOR_FIELDS 22
#endif #endif
}*/ }*/
/*{ /*{
#ifdef DEBUG_PROC
typedef int(*vxscanf)(void*, const char*, va_list);
#endif
typedef struct ProcessList_ { typedef struct ProcessList_ {
TypedVector* processes; Vector* processes;
TypedVector* processes2; Vector* processes2;
Hashtable* processTable; Hashtable* processTable;
Process* prototype; Process* prototype;
UsersTable* usersTable; UsersTable* usersTable;
@ -66,26 +75,39 @@ typedef struct ProcessList_ {
int totalTasks; int totalTasks;
int runningTasks; int runningTasks;
long int* totalTime; // Must match number of PER_PROCESSOR_FIELDS constant
long int* userTime; unsigned long long int* totalTime;
long int* systemTime; unsigned long long int* userTime;
long int* idleTime; unsigned long long int* systemTime;
long int* niceTime; unsigned long long int* systemAllTime;
long int* totalPeriod; unsigned long long int* idleAllTime;
long int* userPeriod; unsigned long long int* idleTime;
long int* systemPeriod; unsigned long long int* niceTime;
long int* idlePeriod; unsigned long long int* ioWaitTime;
long int* nicePeriod; unsigned long long int* irqTime;
unsigned long long int* softIrqTime;
unsigned long long int* stealTime;
unsigned long long int* totalPeriod;
unsigned long long int* userPeriod;
unsigned long long int* systemPeriod;
unsigned long long int* systemAllPeriod;
unsigned long long int* idleAllPeriod;
unsigned long long int* idlePeriod;
unsigned long long int* nicePeriod;
unsigned long long int* ioWaitPeriod;
unsigned long long int* irqPeriod;
unsigned long long int* softIrqPeriod;
unsigned long long int* stealPeriod;
long int totalMem; unsigned long long int totalMem;
long int usedMem; unsigned long long int usedMem;
long int freeMem; unsigned long long int freeMem;
long int sharedMem; unsigned long long int sharedMem;
long int buffersMem; unsigned long long int buffersMem;
long int cachedMem; unsigned long long int cachedMem;
long int totalSwap; unsigned long long int totalSwap;
long int usedSwap; unsigned long long int usedSwap;
long int freeSwap; unsigned long long int freeSwap;
ProcessField* fields; ProcessField* fields;
ProcessField sortKey; ProcessField sortKey;
@ -97,31 +119,27 @@ typedef struct ProcessList_ {
bool treeView; bool treeView;
bool highlightBaseName; bool highlightBaseName;
bool highlightMegabytes; bool highlightMegabytes;
#ifdef DEBUG bool highlightThreads;
bool detailedCPUTime;
#ifdef DEBUG_PROC
FILE* traceFile; FILE* traceFile;
#endif #endif
} ProcessList; } ProcessList;
}*/ }*/
/* private property */ static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
#ifdef DEBUG #ifdef DEBUG_PROC
/* private property */
typedef int(*vxscanf)(void*, const char*, va_list);
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ ) #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__ ) #define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
/* private */ static FILE* ProcessList_fopen(ProcessList* this, const char* path, const char* mode) {
FILE* ProcessList_fopen(ProcessList* this, const char* path, const char* mode) {
fprintf(this->traceFile, "[%s]\n", path); fprintf(this->traceFile, "[%s]\n", path);
return fopen(path, mode); return fopen(path, mode);
} }
/* private */
static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer, char* format, ...) { static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer, char* format, ...) {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
@ -130,7 +148,10 @@ static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer,
va_start(ap, format); va_start(ap, format);
while (*format) { while (*format) {
char ch = *format; char ch = *format;
char* c; int* d; long int* ld; unsigned long int* lu; char** s; char* c; int* d;
long int* ld; unsigned long int* lu;
long long int* lld; unsigned long long int* llu;
char** s;
if (ch != '%') { if (ch != '%') {
fprintf(this->traceFile, "%c", ch); fprintf(this->traceFile, "%c", ch);
format++; format++;
@ -146,6 +167,12 @@ static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer,
switch (*format) { switch (*format) {
case 'd': ld = va_arg(ap, long int*); fprintf(this->traceFile, "%ld", *ld); break; case 'd': ld = va_arg(ap, long int*); fprintf(this->traceFile, "%ld", *ld); break;
case 'u': lu = va_arg(ap, unsigned long int*); fprintf(this->traceFile, "%lu", *lu); break; case 'u': lu = va_arg(ap, unsigned long int*); fprintf(this->traceFile, "%lu", *lu); break;
case 'l':
format++;
switch (*format) {
case 'd': lld = va_arg(ap, long long int*); fprintf(this->traceFile, "%lld", *lld); break;
case 'u': llu = va_arg(ap, unsigned long long int*); fprintf(this->traceFile, "%llu", *llu); break;
}
} }
} }
format++; format++;
@ -165,18 +192,29 @@ static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer,
#endif #endif
static inline void ProcessList_allocatePerProcessorBuffers(ProcessList* this, int procs) {
unsigned long long int** bufferPtr = &(this->totalTime);
unsigned long long int* buffer = calloc(procs * PER_PROCESSOR_FIELDS, sizeof(unsigned long long int));
for (int i = 0; i < PER_PROCESSOR_FIELDS; i++) {
*bufferPtr = buffer;
bufferPtr++;
buffer += procs;
}
}
ProcessList* ProcessList_new(UsersTable* usersTable) { ProcessList* ProcessList_new(UsersTable* usersTable) {
ProcessList* this; ProcessList* this;
this = malloc(sizeof(ProcessList)); this = malloc(sizeof(ProcessList));
this->processes = TypedVector_new(PROCESS_CLASS, true, DEFAULT_SIZE); this->processes = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
this->processTable = Hashtable_new(20, false); this->processTable = Hashtable_new(70, false);
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
this->prototype = Process_new(this); this->prototype = Process_new(this);
this->usersTable = usersTable; this->usersTable = usersTable;
/* tree-view auxiliary buffers */ /* tree-view auxiliary buffers */
this->processes2 = TypedVector_new(PROCESS_CLASS, true, DEFAULT_SIZE); this->processes2 = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
#ifdef DEBUG #ifdef DEBUG_PROC
this->traceFile = fopen("/tmp/htop-proc-trace", "w"); this->traceFile = fopen("/tmp/htop-proc-trace", "w");
#endif #endif
@ -190,23 +228,16 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
} while (String_startsWith(buffer, "cpu")); } while (String_startsWith(buffer, "cpu"));
fclose(status); fclose(status);
this->processorCount = procs - 1; this->processorCount = procs - 1;
this->totalTime = calloc(procs, sizeof(long int));
this->userTime = calloc(procs, sizeof(long int)); ProcessList_allocatePerProcessorBuffers(this, procs);
this->systemTime = calloc(procs, sizeof(long int));
this->niceTime = calloc(procs, sizeof(long int));
this->idleTime = calloc(procs, sizeof(long int));
this->totalPeriod = calloc(procs, sizeof(long int));
this->userPeriod = calloc(procs, sizeof(long int));
this->systemPeriod = calloc(procs, sizeof(long int));
this->nicePeriod = calloc(procs, sizeof(long int));
this->idlePeriod = calloc(procs, sizeof(long int));
for (int i = 0; i < procs; i++) { for (int i = 0; i < procs; i++) {
this->totalTime[i] = 1; this->totalTime[i] = 1;
this->totalPeriod[i] = 1; this->totalPeriod[i] = 1;
} }
this->fields = calloc(sizeof(ProcessField), LAST_PROCESSFIELD+1); this->fields = calloc(sizeof(ProcessField), LAST_PROCESSFIELD+1);
// TODO: turn 'fields' into a TypedVector, // TODO: turn 'fields' into a Vector,
// (and ProcessFields into proper objects). // (and ProcessFields into proper objects).
for (int i = 0; defaultHeaders[i]; i++) { for (int i = 0; defaultHeaders[i]; i++) {
this->fields[i] = defaultHeaders[i]; this->fields[i] = defaultHeaders[i];
@ -220,28 +251,22 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
this->treeView = false; this->treeView = false;
this->highlightBaseName = false; this->highlightBaseName = false;
this->highlightMegabytes = false; this->highlightMegabytes = false;
this->detailedCPUTime = false;
return this; return this;
} }
void ProcessList_delete(ProcessList* this) { void ProcessList_delete(ProcessList* this) {
Hashtable_delete(this->processTable); Hashtable_delete(this->processTable);
TypedVector_delete(this->processes); Vector_delete(this->processes);
TypedVector_delete(this->processes2); Vector_delete(this->processes2);
Process_delete((Object*)this->prototype); Process_delete((Object*)this->prototype);
// Free first entry only;
// other fields are offsets of the same buffer
free(this->totalTime); free(this->totalTime);
free(this->userTime);
free(this->systemTime);
free(this->niceTime);
free(this->idleTime);
free(this->totalPeriod);
free(this->userPeriod);
free(this->systemPeriod);
free(this->nicePeriod);
free(this->idlePeriod);
#ifdef DEBUG #ifdef DEBUG_PROC
fclose(this->traceFile); fclose(this->traceFile);
#endif #endif
@ -257,10 +282,11 @@ void ProcessList_invertSortOrder(ProcessList* this) {
} }
RichString ProcessList_printHeader(ProcessList* this) { RichString ProcessList_printHeader(ProcessList* this) {
RichString out = RichString_new(); RichString out;
RichString_initVal(out);
ProcessField* fields = this->fields; ProcessField* fields = this->fields;
for (int i = 0; fields[i]; i++) { for (int i = 0; fields[i]; i++) {
char* field = Process_printField(fields[i]); char* field = Process_fieldTitles[fields[i]];
if (this->sortKey == fields[i]) if (this->sortKey == fields[i])
RichString_append(&out, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field); RichString_append(&out, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field);
else else
@ -269,92 +295,113 @@ RichString ProcessList_printHeader(ProcessList* this) {
return out; return out;
} }
static void ProcessList_add(ProcessList* this, Process* p) {
void ProcessList_prune(ProcessList* this) { assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1);
TypedVector_prune(this->processes); assert(Hashtable_get(this->processTable, p->pid) == NULL);
} Vector_add(this->processes, p);
void ProcessList_add(ProcessList* this, Process* p) {
TypedVector_add(this->processes, p);
Hashtable_put(this->processTable, p->pid, p); Hashtable_put(this->processTable, p->pid, p);
assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1);
assert(Hashtable_get(this->processTable, p->pid) != NULL);
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
} }
void ProcessList_remove(ProcessList* this, Process* p) { static void ProcessList_remove(ProcessList* this, Process* p) {
Hashtable_remove(this->processTable, p->pid); assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1);
ProcessField pf = this->sortKey; assert(Hashtable_get(this->processTable, p->pid) != NULL);
this->sortKey = PID; Process* pp = Hashtable_remove(this->processTable, p->pid);
int index = TypedVector_indexOf(this->processes, p); assert(pp == p); (void)pp;
TypedVector_remove(this->processes, index); unsigned int pid = p->pid;
this->sortKey = pf; int index = Vector_indexOf(this->processes, p, Process_pidCompare);
assert(index != -1);
Vector_remove(this->processes, index);
assert(Hashtable_get(this->processTable, pid) == NULL); (void)pid;
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
} }
Process* ProcessList_get(ProcessList* this, int index) { Process* ProcessList_get(ProcessList* this, int index) {
return (Process*) (TypedVector_get(this->processes, index)); return (Process*) (Vector_get(this->processes, index));
} }
int ProcessList_size(ProcessList* this) { int ProcessList_size(ProcessList* this) {
return (TypedVector_size(this->processes)); return (Vector_size(this->processes));
} }
/* private */ static void ProcessList_buildTree(ProcessList* this, int pid, int level, int indent, int direction) {
void ProcessList_buildTree(ProcessList* this, int pid, int level, int indent, int direction) { Vector* children = Vector_new(PROCESS_CLASS, false, DEFAULT_SIZE, Process_compare);
TypedVector* children = TypedVector_new(PROCESS_CLASS, false, DEFAULT_SIZE);
for (int i = 0; i < TypedVector_size(this->processes); i++) { for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
Process* process = (Process*) (TypedVector_get(this->processes, i)); Process* process = (Process*) (Vector_get(this->processes, i));
if (process->ppid == pid) { if (process->tgid == pid || (process->tgid == process->pid && process->ppid == pid)) {
Process* process = (Process*) (TypedVector_take(this->processes, i)); Process* process = (Process*) (Vector_take(this->processes, i));
TypedVector_add(children, process); Vector_add(children, process);
i--;
} }
} }
int size = TypedVector_size(children); int size = Vector_size(children);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Process* process = (Process*) (TypedVector_get(children, i)); Process* process = (Process*) (Vector_get(children, i));
int s = this->processes2->items;
if (direction == 1) if (direction == 1)
TypedVector_add(this->processes2, process); Vector_add(this->processes2, process);
else else
TypedVector_insert(this->processes2, 0, process); Vector_insert(this->processes2, 0, process);
assert(this->processes2->items == s+1); (void)s;
int nextIndent = indent; int nextIndent = indent;
if (i < size - 1) if (i < size - 1)
nextIndent = indent | (1 << level); nextIndent = indent | (1 << level);
ProcessList_buildTree(this, process->pid, level+1, nextIndent, direction); ProcessList_buildTree(this, process->pid, level+1, nextIndent, direction);
process->indent = indent | (1 << level); process->indent = indent | (1 << level);
} }
TypedVector_delete(children); Vector_delete(children);
} }
void ProcessList_sort(ProcessList* this) { void ProcessList_sort(ProcessList* this) {
if (!this->treeView) { if (!this->treeView) {
TypedVector_sort(this->processes); Vector_sort(this->processes);
} else { } else {
// Save settings
int direction = this->direction; int direction = this->direction;
int sortKey = this->sortKey; int sortKey = this->sortKey;
// Sort by PID
this->sortKey = PID; this->sortKey = PID;
this->direction = 1; this->direction = 1;
TypedVector_sort(this->processes); Vector_sort(this->processes);
// Restore settings
this->sortKey = sortKey; this->sortKey = sortKey;
this->direction = direction; this->direction = direction;
Process* init = (Process*) (TypedVector_take(this->processes, 0)); // Take PID 1 as root and add to the new listing
assert(init->pid == 1); int vsize = Vector_size(this->processes);
Process* init = (Process*) (Vector_take(this->processes, 0));
// This assertion crashes on hardened kernels.
// I wonder how well tree view works on those systems.
// assert(init->pid == 1);
init->indent = 0; init->indent = 0;
TypedVector_add(this->processes2, init); Vector_add(this->processes2, init);
// Recursively empty list
ProcessList_buildTree(this, init->pid, 0, 0, direction); ProcessList_buildTree(this, init->pid, 0, 0, direction);
TypedVector* t = this->processes; // Add leftovers
while (Vector_size(this->processes)) {
Process* p = (Process*) (Vector_take(this->processes, 0));
p->indent = 0;
Vector_add(this->processes2, p);
ProcessList_buildTree(this, p->pid, 0, 0, direction);
}
assert(Vector_size(this->processes2) == vsize); (void)vsize;
assert(Vector_size(this->processes) == 0);
// Swap listings around
Vector* t = this->processes;
this->processes = this->processes2; this->processes = this->processes2;
this->processes2 = t; this->processes2 = t;
} }
} }
/* private */ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *command) {
int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *command) {
static char buf[MAX_READ]; static char buf[MAX_READ];
long int zero; unsigned long int zero;
int size = fread(buf, 1, MAX_READ, f); int size = fread(buf, 1, MAX_READ, f);
if(!size) return 0; if(!size) return 0;
proc->pid = atoi(buf); assert(proc->pid == atoi(buf));
char *location = strchr(buf, ' '); char *location = strchr(buf, ' ');
if(!location) return 0; if(!location) return 0;
@ -367,21 +414,42 @@ int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *co
command[commsize] = '\0'; command[commsize] = '\0';
location = end + 2; location = end + 2;
#ifdef DEBUG_PROC
int num = ProcessList_read(this, location, int num = ProcessList_read(this, location,
"%c %d %d %d %d %d %lu %lu %lu %lu " "%c %u %u %u %u %d %lu %lu %lu %lu "
"%lu %lu %lu %ld %ld %ld %ld %ld %ld " "%lu %lu %lu %ld %ld %ld %ld %ld %ld "
"%lu %lu %ld %lu %lu %lu %lu %lu " "%lu %lu %ld %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu %lu %lu %lu %lu " "%lu %lu %lu %lu %lu %lu %lu %lu "
"%d %d", "%d %d",
&proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr, &proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
&proc->tpgid, &proc->flags, &proc->minflt, &proc->cminflt, &proc->majflt, &proc->tpgid, &proc->flags,
&proc->cmajflt, &proc->utime, &proc->stime, &proc->cutime, &proc->cstime, &proc->minflt, &proc->cminflt, &proc->majflt, &proc->cmajflt,
&proc->priority, &proc->nice, &zero, &proc->itrealvalue, &proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
&proc->priority, &proc->nice, &proc->nlwp, &proc->itrealvalue,
&proc->starttime, &proc->vsize, &proc->rss, &proc->rlim, &proc->starttime, &proc->vsize, &proc->rss, &proc->rlim,
&proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp, &proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp,
&proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore, &proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore,
&proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap, &proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap,
&proc->exit_signal, &proc->processor); &proc->exit_signal, &proc->processor);
#else
long int uzero;
int num = ProcessList_read(this, location,
"%c %u %u %u %u %d %lu %lu %lu %lu "
"%lu %lu %lu %ld %ld %ld %ld %ld %ld "
"%lu %lu %ld %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu %lu %lu %lu %lu "
"%d %d",
&proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
&proc->tpgid, &proc->flags,
&zero, &zero, &zero, &zero,
&proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
&proc->priority, &proc->nice, &proc->nlwp, &uzero,
&zero, &zero, &uzero, &zero,
&zero, &zero, &zero, &zero,
&zero, &zero, &zero, &zero,
&zero, &zero, &zero, &zero,
&proc->exit_signal, &proc->processor);
#endif
// This assert is always valid on 2.4, but reportedly not always valid on 2.6. // This assert is always valid on 2.4, but reportedly not always valid on 2.6.
// TODO: Check if the semantics of this field has changed. // TODO: Check if the semantics of this field has changed.
@ -391,50 +459,72 @@ int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *co
return 1; return 1;
} }
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name) { static bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name) {
char statusfilename[MAX_NAME+1]; char statusfilename[MAX_NAME+1];
statusfilename[MAX_NAME] = '\0'; statusfilename[MAX_NAME] = '\0';
snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
FILE* status = ProcessList_fopen(this, statusfilename, "r"); snprintf(statusfilename, MAX_NAME, "%s/%s", dirname, name);
bool success = false;
if (status) {
char buffer[1024];
buffer[1023] = '\0';
while (!feof(status)) {
char* ok = fgets(buffer, 1023, status);
if (!ok)
break;
if (String_startsWith(buffer, "Uid:")) {
int uid1, uid2, uid3, uid4;
// TODO: handle other uid's.
int ok = ProcessList_read(this, buffer, "Uid:\t%d\t%d\t%d\t%d", &uid1, &uid2, &uid3, &uid4);
if (ok >= 1) {
proc->st_uid = uid1;
success = true;
}
break;
}
}
fclose(status);
}
if (!success) {
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
struct stat sstat; struct stat sstat;
int statok = stat(statusfilename, &sstat); int statok = stat(statusfilename, &sstat);
if (statok == -1) if (statok == -1)
return false; return false;
proc->st_uid = sstat.st_uid; proc->st_uid = sstat.st_uid;
} return true;
return success;
} }
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period) { #ifdef HAVE_TASKSTATS
static void ProcessList_readIoFile(ProcessList* this, Process* proc, char* dirname, char* name) {
char iofilename[MAX_NAME+1];
iofilename[MAX_NAME] = '\0';
snprintf(iofilename, MAX_NAME, "%s/%s/io", dirname, name);
FILE* io = ProcessList_fopen(this, iofilename, "r");
if (io) {
char buffer[256];
buffer[255] = '\0';
struct timeval tv;
gettimeofday(&tv,NULL);
unsigned long long now = tv.tv_sec*1000+tv.tv_usec/1000;
unsigned long long last_read = proc->io_read_bytes;
unsigned long long last_write = proc->io_write_bytes;
while (!feof(io)) {
char* ok = fgets(buffer, 255, io);
if (!ok)
break;
if (ProcessList_read(this, buffer, "rchar: %llu", &proc->io_rchar)) continue;
if (ProcessList_read(this, buffer, "wchar: %llu", &proc->io_wchar)) continue;
if (ProcessList_read(this, buffer, "syscr: %llu", &proc->io_syscr)) continue;
if (ProcessList_read(this, buffer, "syscw: %llu", &proc->io_syscw)) continue;
if (ProcessList_read(this, buffer, "read_bytes: %llu", &proc->io_read_bytes)) {
proc->io_rate_read_bps =
((double)(proc->io_read_bytes - last_read))/(((double)(now - proc->io_rate_read_time))/1000);
proc->io_rate_read_time = now;
continue;
}
if (ProcessList_read(this, buffer, "write_bytes: %llu", &proc->io_write_bytes)) {
proc->io_rate_write_bps =
((double)(proc->io_write_bytes - last_write))/(((double)(now - proc->io_rate_write_time))/1000);
proc->io_rate_write_time = now;
continue;
}
ProcessList_read(this, buffer, "cancelled_write_bytes: %llu", &proc->io_cancelled_write_bytes);
}
fclose(io);
}
}
#endif
static bool ProcessList_processEntries(ProcessList* this, char* dirname, Process* parent, float period) {
DIR* dir; DIR* dir;
struct dirent* entry; struct dirent* entry;
Process* prototype = this->prototype; Process* prototype = this->prototype;
dir = opendir(dirname); dir = opendir(dirname);
assert(dir != NULL); if (!dir) return false;
int processors = this->processorCount;
bool showUserlandThreads = !this->hideUserlandThreads;
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
char* name = entry->d_name; char* name = entry->d_name;
int pid; int pid;
@ -451,39 +541,65 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
isThread = true; isThread = true;
} }
if (pid > 0 && pid != parent) { if (pid > 0) {
if (!this->hideUserlandThreads) {
char subdirname[MAX_NAME+1];
snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
if (access(subdirname, X_OK) == 0) {
ProcessList_processEntries(this, subdirname, pid, period);
}
}
FILE* status; FILE* status;
char statusfilename[MAX_NAME+1]; char statusfilename[MAX_NAME+1];
char command[PROCESS_COMM_LEN + 1]; char command[PROCESS_COMM_LEN + 1];
Process* process; Process* process = NULL;
Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid); Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid);
if (!existingProcess) {
process = Process_clone(prototype); if (existingProcess) {
process->pid = pid; assert(Vector_indexOf(this->processes, existingProcess, Process_pidCompare) != -1);
ProcessList_add(this, process);
if (! ProcessList_readStatusFile(this, process, dirname, name))
goto errorReadingProcess;
} else {
process = existingProcess; process = existingProcess;
assert(process->pid == pid);
} else {
if (parent && parent->pid == pid) {
process = parent;
} else {
process = prototype;
assert(process->comm == NULL);
process->pid = pid;
} }
}
process->tgid = parent ? parent->pid : pid;
if (showUserlandThreads && (!parent || pid != parent->pid)) {
char subdirname[MAX_NAME+1];
snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
if (ProcessList_processEntries(this, subdirname, process, period))
continue;
}
#ifdef HAVE_TASKSTATS
ProcessList_readIoFile(this, process, dirname, name);
#endif
process->updated = true; process->updated = true;
char* username = UsersTable_getRef(this->usersTable, process->st_uid); if (!existingProcess)
if (username) { if (! ProcessList_readStatusFile(this, process, dirname, name))
strncpy(process->user, username, PROCESS_USER_LEN); goto errorReadingProcess;
} else {
snprintf(process->user, PROCESS_USER_LEN, "%d", process->st_uid); snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r");
if(!status) {
goto errorReadingProcess;
} }
int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
&process->m_size, &process->m_resident, &process->m_share,
&process->m_trs, &process->m_lrs, &process->m_drs,
&process->m_dt);
fclose(status);
if(num != 7)
goto errorReadingProcess;
if (this->hideKernelThreads && process->m_size == 0)
goto errorReadingProcess;
int lasttimes = (process->utime + process->stime); int lasttimes = (process->utime + process->stime);
@ -499,10 +615,65 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
goto errorReadingProcess; goto errorReadingProcess;
} }
process->percent_cpu = (process->utime + process->stime - lasttimes) /
period * 100.0;
if(!existingProcess) { if(!existingProcess) {
process->user = UsersTable_getRef(this->usersTable, process->st_uid);
#ifdef HAVE_OPENVZ
if (access("/proc/vz", R_OK) != 0) {
process->vpid = process->pid;
process->ctid = 0;
} else {
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r");
if (status == NULL)
goto errorReadingProcess;
num = ProcessList_fread(this, status,
"%*u %*s %*c %*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u "
"%*u %*u %u %u",
&process->vpid, &process->ctid);
fclose(status);
}
#endif
#ifdef HAVE_VSERVER
snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r");
if (status == NULL)
goto errorReadingProcess;
else {
char buffer[256];
process->vxid = 0;
while (!feof(status)) {
char* ok = fgets(buffer, 255, status);
if (!ok)
break;
if (String_startsWith(buffer, "VxID:")) {
int vxid;
int ok = ProcessList_read(this, buffer, "VxID:\t%d", &vxid);
if (ok >= 1) {
process->vxid = vxid;
}
}
#if defined HAVE_ANCIENT_VSERVER
else if (String_startsWith(buffer, "s_context:")) {
int vxid;
int ok = ProcessList_read(this, buffer, "s_context:\t%d", &vxid);
if (ok >= 1) {
process->vxid = vxid;
}
}
#endif
}
fclose(status);
}
#endif
snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name); snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r"); status = ProcessList_fopen(this, statusfilename, "r");
if (!status) { if (!status) {
@ -521,23 +692,12 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
fclose(status); fclose(status);
} }
snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name); int percent_cpu = (process->utime + process->stime - lasttimes) /
status = ProcessList_fopen(this, statusfilename, "r"); period * 100.0;
process->percent_cpu = MAX(MIN(percent_cpu, processors*100.0), 0.0);
if(!status) { process->percent_mem = (process->m_resident * PAGE_SIZE_KB) /
goto errorReadingProcess; (float)(this->totalMem) *
}
int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
&process->m_size, &process->m_resident, &process->m_share,
&process->m_trs, &process->m_drs, &process->m_lrs,
&process->m_dt);
fclose(status);
if(num != 7)
goto errorReadingProcess;
process->percent_mem = process->m_resident /
(float)(this->usedMem - this->cachedMem - this->buffersMem) *
100.0; 100.0;
this->totalTasks++; this->totalTasks++;
@ -545,53 +705,63 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
this->runningTasks++; this->runningTasks++;
} }
if (this->hideKernelThreads && process->m_size == 0) if (!existingProcess) {
ProcessList_remove(this, process); process = Process_clone(process);
ProcessList_add(this, process);
}
continue; continue;
// Exception handler. // Exception handler.
errorReadingProcess: { errorReadingProcess: {
if (process->comm) {
free(process->comm);
process->comm = NULL;
}
if (existingProcess)
ProcessList_remove(this, process); ProcessList_remove(this, process);
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
} }
} }
} }
closedir(dir); closedir(dir);
return true;
} }
void ProcessList_scan(ProcessList* this) { void ProcessList_scan(ProcessList* this) {
long int usertime, nicetime, systemtime, idletime, totaltime; unsigned long long int usertime, nicetime, systemtime, systemalltime, idlealltime, idletime, totaltime;
long int swapFree; unsigned long long int swapFree;
FILE* status; FILE* status;
char buffer[128]; char buffer[128];
status = ProcessList_fopen(this, PROCMEMINFOFILE, "r"); status = ProcessList_fopen(this, PROCMEMINFOFILE, "r");
assert(status != NULL); assert(status != NULL);
int processors = this->processorCount;
while (!feof(status)) { while (!feof(status)) {
fgets(buffer, 128, status); fgets(buffer, 128, status);
switch (buffer[0]) { switch (buffer[0]) {
case 'M': case 'M':
if (String_startsWith(buffer, "MemTotal:")) if (String_startsWith(buffer, "MemTotal:"))
ProcessList_read(this, buffer, "MemTotal: %ld kB", &this->totalMem); ProcessList_read(this, buffer, "MemTotal: %llu kB", &this->totalMem);
else if (String_startsWith(buffer, "MemFree:")) else if (String_startsWith(buffer, "MemFree:"))
ProcessList_read(this, buffer, "MemFree: %ld kB", &this->freeMem); ProcessList_read(this, buffer, "MemFree: %llu kB", &this->freeMem);
else if (String_startsWith(buffer, "MemShared:")) else if (String_startsWith(buffer, "MemShared:"))
ProcessList_read(this, buffer, "MemShared: %ld kB", &this->sharedMem); ProcessList_read(this, buffer, "MemShared: %llu kB", &this->sharedMem);
break; break;
case 'B': case 'B':
if (String_startsWith(buffer, "Buffers:")) if (String_startsWith(buffer, "Buffers:"))
ProcessList_read(this, buffer, "Buffers: %ld kB", &this->buffersMem); ProcessList_read(this, buffer, "Buffers: %llu kB", &this->buffersMem);
break; break;
case 'C': case 'C':
if (String_startsWith(buffer, "Cached:")) if (String_startsWith(buffer, "Cached:"))
ProcessList_read(this, buffer, "Cached: %ld kB", &this->cachedMem); ProcessList_read(this, buffer, "Cached: %llu kB", &this->cachedMem);
break; break;
case 'S': case 'S':
if (String_startsWith(buffer, "SwapTotal:")) if (String_startsWith(buffer, "SwapTotal:"))
ProcessList_read(this, buffer, "SwapTotal: %ld kB", &this->totalSwap); ProcessList_read(this, buffer, "SwapTotal: %llu kB", &this->totalSwap);
if (String_startsWith(buffer, "SwapFree:")) if (String_startsWith(buffer, "SwapFree:"))
ProcessList_read(this, buffer, "SwapFree: %ld kB", &swapFree); ProcessList_read(this, buffer, "SwapFree: %llu kB", &swapFree);
break; break;
} }
} }
@ -603,60 +773,76 @@ void ProcessList_scan(ProcessList* this) {
status = ProcessList_fopen(this, PROCSTATFILE, "r"); status = ProcessList_fopen(this, PROCSTATFILE, "r");
assert(status != NULL); assert(status != NULL);
for (int i = 0; i <= this->processorCount; i++) { for (int i = 0; i <= processors; i++) {
char buffer[256]; char buffer[256];
int cpuid; int cpuid;
long int ioWait, irq, softIrq, steal; unsigned long long int ioWait, irq, softIrq, steal;
ioWait = irq = softIrq = steal = 0; ioWait = irq = softIrq = steal = 0;
// Dependending on your kernel version, // Dependending on your kernel version,
// 5, 7 or 8 of these fields will be set. // 5, 7 or 8 of these fields will be set.
// The rest will remain at zero. // The rest will remain at zero.
fgets(buffer, 255, status); fgets(buffer, 255, status);
if (i == 0) if (i == 0)
ProcessList_read(this, buffer, "cpu %ld %ld %ld %ld %ld %ld %ld %ld", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal); ProcessList_read(this, buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal);
else { else {
ProcessList_read(this, buffer, "cpu%d %ld %ld %ld %ld %ld %ld %ld %ld", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal); ProcessList_read(this, buffer, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal);
assert(cpuid == i - 1); assert(cpuid == i - 1);
} }
// Fields existing on kernels >= 2.6 // Fields existing on kernels >= 2.6
// (and RHEL's patched kernel 2.4...) // (and RHEL's patched kernel 2.4...)
systemtime += ioWait + irq + softIrq + steal; idlealltime = idletime + ioWait;
totaltime = usertime + nicetime + systemtime + idletime; systemalltime = systemtime + irq + softIrq + steal;
totaltime = usertime + nicetime + systemalltime + idlealltime;
assert (usertime >= this->userTime[i]); assert (usertime >= this->userTime[i]);
assert (nicetime >= this->niceTime[i]); assert (nicetime >= this->niceTime[i]);
assert (systemtime >= this->systemTime[i]); assert (systemtime >= this->systemTime[i]);
assert (idletime >= this->idleTime[i]); assert (idletime >= this->idleTime[i]);
assert (totaltime >= this->totalTime[i]); assert (totaltime >= this->totalTime[i]);
assert (systemalltime >= this->systemAllTime[i]);
assert (idlealltime >= this->idleAllTime[i]);
assert (ioWait >= this->ioWaitTime[i]);
assert (irq >= this->irqTime[i]);
assert (softIrq >= this->softIrqTime[i]);
assert (steal >= this->stealTime[i]);
this->userPeriod[i] = usertime - this->userTime[i]; this->userPeriod[i] = usertime - this->userTime[i];
this->nicePeriod[i] = nicetime - this->niceTime[i]; this->nicePeriod[i] = nicetime - this->niceTime[i];
this->systemPeriod[i] = systemtime - this->systemTime[i]; this->systemPeriod[i] = systemtime - this->systemTime[i];
this->systemAllPeriod[i] = systemalltime - this->systemAllTime[i];
this->idleAllPeriod[i] = idlealltime - this->idleAllTime[i];
this->idlePeriod[i] = idletime - this->idleTime[i]; this->idlePeriod[i] = idletime - this->idleTime[i];
this->ioWaitPeriod[i] = ioWait - this->ioWaitTime[i];
this->irqPeriod[i] = irq - this->irqTime[i];
this->softIrqPeriod[i] = softIrq - this->softIrqTime[i];
this->stealPeriod[i] = steal - this->stealTime[i];
this->totalPeriod[i] = totaltime - this->totalTime[i]; this->totalPeriod[i] = totaltime - this->totalTime[i];
this->userTime[i] = usertime; this->userTime[i] = usertime;
this->niceTime[i] = nicetime; this->niceTime[i] = nicetime;
this->systemTime[i] = systemtime; this->systemTime[i] = systemtime;
this->systemAllTime[i] = systemalltime;
this->idleAllTime[i] = idlealltime;
this->idleTime[i] = idletime; this->idleTime[i] = idletime;
this->ioWaitTime[i] = ioWait;
this->irqTime[i] = irq;
this->softIrqTime[i] = softIrq;
this->stealTime[i] = steal;
this->totalTime[i] = totaltime; this->totalTime[i] = totaltime;
} }
float period = (float)this->totalPeriod[0] / this->processorCount; float period = (float)this->totalPeriod[0] / processors;
fclose(status); fclose(status);
// mark all process as "dirty" // mark all process as "dirty"
for (int i = 0; i < TypedVector_size(this->processes); i++) { for (int i = 0; i < Vector_size(this->processes); i++) {
Process* p = (Process*) TypedVector_get(this->processes, i); Process* p = (Process*) Vector_get(this->processes, i);
p->updated = false; p->updated = false;
} }
this->totalTasks = 0; this->totalTasks = 0;
this->runningTasks = 0; this->runningTasks = 0;
signal(11, ProcessList_dontCrash); ProcessList_processEntries(this, PROCDIR, NULL, period);
ProcessList_processEntries(this, PROCDIR, 0, period); for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
signal(11, SIG_DFL); Process* p = (Process*) Vector_get(this->processes, i);
for (int i = TypedVector_size(this->processes) - 1; i >= 0; i--) {
Process* p = (Process*) TypedVector_get(this->processes, i);
if (p->updated == false) if (p->updated == false)
ProcessList_remove(this, p); ProcessList_remove(this, p);
else else
@ -665,8 +851,16 @@ void ProcessList_scan(ProcessList* this) {
} }
void ProcessList_dontCrash(int signal) { ProcessField ProcessList_keyAt(ProcessList* this, int at) {
// This ugly hack was added because I suspect some int x = 0;
// crashes were caused by contents of /proc vanishing ProcessField* fields = this->fields;
// away while we read them. ProcessField field;
for (int i = 0; (field = fields[i]); i++) {
int len = strlen(Process_fieldTitles[field]);
if (at >= x && at <= x + len) {
return field;
}
x += len;
}
return COMM;
} }

View File

@ -3,7 +3,7 @@
#ifndef HEADER_ProcessList #ifndef HEADER_ProcessList
#define HEADER_ProcessList #define HEADER_ProcessList
/* /*
htop - ProcessList.c htop - ProcessList.h
(C) 2004,2005 Hisham H. Muhammad (C) 2004,2005 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -15,9 +15,10 @@ in the source distribution for its full text.
#endif #endif
#include "Process.h" #include "Process.h"
#include "TypedVector.h" #include "Vector.h"
#include "UsersTable.h" #include "UsersTable.h"
#include "Hashtable.h" #include "Hashtable.h"
#include "String.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -38,11 +39,11 @@ in the source distribution for its full text.
#endif #endif
#ifndef PROCSTATFILE #ifndef PROCSTATFILE
#define PROCSTATFILE "/proc/stat" #define PROCSTATFILE PROCDIR "/stat"
#endif #endif
#ifndef PROCMEMINFOFILE #ifndef PROCMEMINFOFILE
#define PROCMEMINFOFILE "/proc/meminfo" #define PROCMEMINFOFILE PROCDIR "/meminfo"
#endif #endif
#ifndef MAX_NAME #ifndef MAX_NAME
@ -50,14 +51,22 @@ in the source distribution for its full text.
#endif #endif
#ifndef MAX_READ #ifndef MAX_READ
#define MAX_READ 8192 #define MAX_READ 2048
#endif
#ifndef PER_PROCESSOR_FIELDS
#define PER_PROCESSOR_FIELDS 22
#endif #endif
#ifdef DEBUG_PROC
typedef int(*vxscanf)(void*, const char*, va_list);
#endif
typedef struct ProcessList_ { typedef struct ProcessList_ {
TypedVector* processes; Vector* processes;
TypedVector* processes2; Vector* processes2;
Hashtable* processTable; Hashtable* processTable;
Process* prototype; Process* prototype;
UsersTable* usersTable; UsersTable* usersTable;
@ -66,26 +75,39 @@ typedef struct ProcessList_ {
int totalTasks; int totalTasks;
int runningTasks; int runningTasks;
long int* totalTime; // Must match number of PER_PROCESSOR_FIELDS constant
long int* userTime; unsigned long long int* totalTime;
long int* systemTime; unsigned long long int* userTime;
long int* idleTime; unsigned long long int* systemTime;
long int* niceTime; unsigned long long int* systemAllTime;
long int* totalPeriod; unsigned long long int* idleAllTime;
long int* userPeriod; unsigned long long int* idleTime;
long int* systemPeriod; unsigned long long int* niceTime;
long int* idlePeriod; unsigned long long int* ioWaitTime;
long int* nicePeriod; unsigned long long int* irqTime;
unsigned long long int* softIrqTime;
unsigned long long int* stealTime;
unsigned long long int* totalPeriod;
unsigned long long int* userPeriod;
unsigned long long int* systemPeriod;
unsigned long long int* systemAllPeriod;
unsigned long long int* idleAllPeriod;
unsigned long long int* idlePeriod;
unsigned long long int* nicePeriod;
unsigned long long int* ioWaitPeriod;
unsigned long long int* irqPeriod;
unsigned long long int* softIrqPeriod;
unsigned long long int* stealPeriod;
long int totalMem; unsigned long long int totalMem;
long int usedMem; unsigned long long int usedMem;
long int freeMem; unsigned long long int freeMem;
long int sharedMem; unsigned long long int sharedMem;
long int buffersMem; unsigned long long int buffersMem;
long int cachedMem; unsigned long long int cachedMem;
long int totalSwap; unsigned long long int totalSwap;
long int usedSwap; unsigned long long int usedSwap;
long int freeSwap; unsigned long long int freeSwap;
ProcessField* fields; ProcessField* fields;
ProcessField sortKey; ProcessField sortKey;
@ -97,21 +119,19 @@ typedef struct ProcessList_ {
bool treeView; bool treeView;
bool highlightBaseName; bool highlightBaseName;
bool highlightMegabytes; bool highlightMegabytes;
#ifdef DEBUG bool highlightThreads;
bool detailedCPUTime;
#ifdef DEBUG_PROC
FILE* traceFile; FILE* traceFile;
#endif #endif
} ProcessList; } ProcessList;
#ifdef DEBUG_PROC
#ifdef DEBUG
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ ) #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__ ) #define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
#else #else
#ifndef ProcessList_read #ifndef ProcessList_read
@ -130,27 +150,18 @@ void ProcessList_invertSortOrder(ProcessList* this);
RichString ProcessList_printHeader(ProcessList* this); RichString ProcessList_printHeader(ProcessList* this);
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 index);
int ProcessList_size(ProcessList* this); int ProcessList_size(ProcessList* this);
void ProcessList_sort(ProcessList* this); void ProcessList_sort(ProcessList* this);
#ifdef HAVE_TASKSTATS
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name); #endif
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period);
void ProcessList_scan(ProcessList* this); void ProcessList_scan(ProcessList* this);
void ProcessList_dontCrash(int signal); ProcessField ProcessList_keyAt(ProcessList* this, int at);
#endif #endif

6
README
View File

@ -2,13 +2,15 @@
htop htop
by Hisham Muhammad <loderunner@users.sourceforge.net> by Hisham Muhammad <loderunner@users.sourceforge.net>
May, 2004 - March, 2006 May, 2004 - June, 2009
Introduction Introduction
~~~~~~~~~~~~ ~~~~~~~~~~~~
This is htop, an interactive process viewer. This is htop, an interactive process viewer.
It requires ncurses. Tested with Linux 2.4 and 2.6. It requires ncurses. It is tested with Linux 2.6,
but is also reported to work (and was originally developed)
with the 2.4 series.
Note that, while, htop is Linux specific -- it is based Note that, while, htop is Linux specific -- it is based
on the Linux /proc filesystem -- it is also reported to work on the Linux /proc filesystem -- it is also reported to work

View File

@ -1,20 +1,47 @@
#include "RichString.h" #include "RichString.h"
#ifndef CONFIG_H
#define CONFIG_H
#include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <curses.h> #include <ctype.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <curses.h>
#else
#include <ncursesw/curses.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
/*{ /*{
#define RichString_init(this) (this)->len = 0
#define RichString_initVal(this) (this).len = 0
#ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i])
#endif
typedef struct RichString_ { typedef struct RichString_ {
int len; int len;
#ifdef HAVE_LIBNCURSESW
cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1]; chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
}*/ }*/
@ -23,61 +50,93 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
#endif #endif
/* private property */ #ifdef HAVE_LIBNCURSESW
WINDOW* workArea = NULL;
RichString RichString_new() { inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
RichString this; wchar_t data[RICHSTRING_MAXLEN];
this.len = 0; len = mbstowcs(data, data_c, RICHSTRING_MAXLEN);
return this; if (len<0)
return;
int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
for (int i = this->len, j = 0; i < last; i++, j++) {
memset(&this->chstr[i], 0, sizeof(this->chstr[i]));
this->chstr[i].chars[0] = data[j];
this->chstr[i].attr = attrs;
}
this->chstr[last].chars[0] = 0;
this->len = last;
} }
void RichString_delete(RichString this) { inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
cchar_t* ch = this->chstr + start;
for (int i = start; i <= finish; i++) {
ch->attr = attrs;
ch++;
}
} }
int RichString_findChar(RichString *this, char c, int start) {
wchar_t wc = btowc(c);
cchar_t* ch = this->chstr + start;
for (int i = start; i < this->len; i++) {
if (ch->chars[0] == wc)
return i;
ch++;
}
return -1;
}
#else
inline void RichString_appendn(RichString* this, int attrs, char* data_c, int len) {
int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
for (int i = this->len, j = 0; i < last; i++, j++)
this->chstr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs;
this->chstr[last] = 0;
this->len = last;
}
void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
chtype* ch = this->chstr + start;
for (int i = start; i <= finish; i++) {
*ch = (*ch & 0xff) | attrs;
ch++;
}
}
int RichString_findChar(RichString *this, char c, int start) {
chtype* ch = this->chstr + start;
for (int i = start; i < this->len; i++) {
if ((*ch & 0xff) == c)
return i;
ch++;
}
return -1;
}
#endif
void RichString_prune(RichString* this) { void RichString_prune(RichString* this) {
this->len = 0; this->len = 0;
} }
void RichString_write(RichString* this, int attrs, char* data) { void RichString_setAttr(RichString *this, int attrs) {
this->len = 0; RichString_setAttrn(this, attrs, 0, this->len - 1);
RichString_append(this, attrs, data);
} }
inline void RichString_append(RichString* this, int attrs, char* data) { inline void RichString_append(RichString* this, int attrs, char* data) {
RichString_appendn(this, attrs, data, strlen(data)); RichString_appendn(this, attrs, data, strlen(data));
} }
inline void RichString_appendn(RichString* this, int attrs, char* data, int len) { void RichString_write(RichString* this, int attrs, char* data) {
if (!workArea) { RichString_init(this);
workArea = newpad(1, RICHSTRING_MAXLEN); RichString_append(this, attrs, data);
}
assert(workArea);
wattrset(workArea, attrs);
int maxToWrite = (RICHSTRING_MAXLEN - 1) - this->len;
int wrote = MIN(maxToWrite, len);
mvwaddnstr(workArea, 0, 0, data, maxToWrite);
int oldstrlen = this->len;
this->len += wrote;
mvwinchnstr(workArea, 0, 0, this->chstr + oldstrlen, wrote);
wattroff(workArea, attrs);
}
void RichString_setAttr(RichString *this, int attrs) {
for (int i = 0; i < this->len; i++) {
char c = this->chstr[i];
this->chstr[i] = c | attrs;
}
}
void RichString_applyAttr(RichString *this, int attrs) {
for (int i = 0; i < this->len - 1; i++) {
this->chstr[i] |= attrs;
}
} }
RichString RichString_quickString(int attrs, char* data) { RichString RichString_quickString(int attrs, char* data) {
RichString str = RichString_new(); RichString str;
RichString_initVal(str);
RichString_write(&str, attrs, data); RichString_write(&str, attrs, data);
return str; return str;
} }

View File

@ -1,42 +1,81 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_RichString #ifndef HEADER_RichString
#define HEADER_RichString #define HEADER_RichString
#ifndef CONFIG_H
#define CONFIG_H
#include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <curses.h> #include <ctype.h>
#include <sys/param.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifdef HAVE_LIBNCURSESW
#include <curses.h>
#else
#include <ncursesw/curses.h>
#endif
#define RICHSTRING_MAXLEN 300 #define RICHSTRING_MAXLEN 300
#define RichString_init(this) (this)->len = 0
#define RichString_initVal(this) (this).len = 0
#ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
#else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
#define RichString_getCharVal(this, i) (this.chstr[i])
#endif
typedef struct RichString_ { typedef struct RichString_ {
int len; int len;
#ifdef HAVE_LIBNCURSESW
cchar_t chstr[RICHSTRING_MAXLEN+1];
#else
chtype chstr[RICHSTRING_MAXLEN+1]; chtype chstr[RICHSTRING_MAXLEN+1];
#endif
} RichString; } RichString;
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
RichString RichString_new(); #ifdef HAVE_LIBNCURSESW
void RichString_delete(RichString this); extern void RichString_appendn(RichString* this, int attrs, char* data_c, int len);
extern void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start);
#else
extern void RichString_appendn(RichString* this, int attrs, char* data_c, int len);
void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
int RichString_findChar(RichString *this, char c, int start);
#endif
void RichString_prune(RichString* this); void RichString_prune(RichString* this);
void RichString_write(RichString* this, int attrs, char* data);
inline void RichString_append(RichString* this, int attrs, char* data);
inline void RichString_appendn(RichString* this, int attrs, char* data, int len);
void RichString_setAttr(RichString *this, int attrs); void RichString_setAttr(RichString *this, int attrs);
void RichString_applyAttr(RichString *this, int attrs); extern void RichString_append(RichString* this, int attrs, char* data);
void RichString_write(RichString* this, int attrs, char* data);
RichString RichString_quickString(int attrs, char* data); RichString RichString_quickString(int attrs, char* data);

View File

@ -6,9 +6,9 @@ in the source distribution for its full text.
*/ */
#include "ScreenManager.h" #include "ScreenManager.h"
#include "ListBox.h" #include "Panel.h"
#include "Object.h" #include "Object.h"
#include "TypedVector.h" #include "Vector.h"
#include "FunctionBar.h" #include "FunctionBar.h"
#include "debug.h" #include "debug.h"
@ -29,8 +29,8 @@ typedef struct ScreenManager_ {
int x2; int x2;
int y2; int y2;
Orientation orientation; Orientation orientation;
TypedVector* items; Vector* items;
TypedVector* fuBars; Vector* fuBars;
int itemCount; int itemCount;
FunctionBar* fuBar; FunctionBar* fuBar;
bool owner; bool owner;
@ -47,16 +47,16 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori
this->y2 = y2; this->y2 = y2;
this->fuBar = NULL; this->fuBar = NULL;
this->orientation = orientation; this->orientation = orientation;
this->items = TypedVector_new(LISTBOX_CLASS, owner, DEFAULT_SIZE); this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
this->fuBars = TypedVector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE); this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
this->itemCount = 0; this->itemCount = 0;
this->owner = owner; this->owner = owner;
return this; return this;
} }
void ScreenManager_delete(ScreenManager* this) { void ScreenManager_delete(ScreenManager* this) {
TypedVector_delete(this->items); Vector_delete(this->items);
TypedVector_delete(this->fuBars); Vector_delete(this->fuBars);
free(this); free(this);
} }
@ -64,44 +64,38 @@ inline int ScreenManager_size(ScreenManager* this) {
return this->itemCount; return this->itemCount;
} }
void ScreenManager_add(ScreenManager* this, ListBox* item, FunctionBar* fuBar, int size) { void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
int lastX = 0; int lastX = 0;
if (this->itemCount > 0) { if (this->itemCount > 0) {
ListBox* last = (ListBox*) TypedVector_get(this->items, this->itemCount - 1); Panel* last = (Panel*) Vector_get(this->items, this->itemCount - 1);
lastX = last->x + last->w + 1; lastX = last->x + last->w + 1;
} }
if (size > 0) { if (size > 0) {
ListBox_resize(item, size, LINES-this->y1+this->y2); Panel_resize(item, size, LINES-this->y1+this->y2);
} else { } else {
ListBox_resize(item, COLS-this->x1+this->x2-lastX, LINES-this->y1+this->y2); Panel_resize(item, COLS-this->x1+this->x2-lastX, LINES-this->y1+this->y2);
} }
ListBox_move(item, lastX, this->y1); Panel_move(item, lastX, this->y1);
} }
// TODO: VERTICAL // TODO: VERTICAL
TypedVector_add(this->items, item); Vector_add(this->items, item);
if (fuBar) if (fuBar)
TypedVector_add(this->fuBars, fuBar); Vector_add(this->fuBars, fuBar);
else else
TypedVector_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; if (!this->fuBar && fuBar) this->fuBar = fuBar;
item->needsRedraw = true; item->needsRedraw = true;
this->itemCount++; this->itemCount++;
} }
ListBox* ScreenManager_remove(ScreenManager* this, int index) { Panel* ScreenManager_remove(ScreenManager* this, int index) {
assert(this->itemCount > index); assert(this->itemCount > index);
ListBox* lb = (ListBox*) TypedVector_remove(this->items, index); Panel* panel = (Panel*) Vector_remove(this->items, index);
TypedVector_remove(this->fuBars, index); Vector_remove(this->fuBars, index);
this->fuBar = NULL; this->fuBar = NULL;
this->itemCount--; this->itemCount--;
return lb; 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) { void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
@ -112,37 +106,37 @@ void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
int items = this->itemCount; int items = this->itemCount;
int lastX = 0; int lastX = 0;
for (int i = 0; i < items - 1; i++) { for (int i = 0; i < items - 1; i++) {
ListBox* lb = (ListBox*) TypedVector_get(this->items, i); Panel* panel = (Panel*) Vector_get(this->items, i);
ListBox_resize(lb, lb->w, LINES-y1+y2); Panel_resize(panel, panel->w, LINES-y1+y2);
ListBox_move(lb, lastX, y1); Panel_move(panel, lastX, y1);
lastX = lb->x + lb->w + 1; lastX = panel->x + panel->w + 1;
} }
ListBox* lb = (ListBox*) TypedVector_get(this->items, items-1); Panel* panel = (Panel*) Vector_get(this->items, items-1);
ListBox_resize(lb, COLS-x1+x2-lastX, LINES-y1+y2); Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
ListBox_move(lb, lastX, y1); Panel_move(panel, lastX, y1);
} }
void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) { void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
bool quit = false; bool quit = false;
int focus = 0; int focus = 0;
ListBox* lbFocus = (ListBox*) TypedVector_get(this->items, focus); Panel* panelFocus = (Panel*) Vector_get(this->items, focus);
if (this->fuBar) if (this->fuBar)
FunctionBar_draw(this->fuBar, NULL); FunctionBar_draw(this->fuBar, NULL);
int ch; int ch = 0;
while (!quit) { while (!quit) {
int items = this->itemCount; int items = this->itemCount;
for (int i = 0; i < items; i++) { for (int i = 0; i < items; i++) {
ListBox* lb = (ListBox*) TypedVector_get(this->items, i); Panel* panel = (Panel*) Vector_get(this->items, i);
ListBox_draw(lb, i == focus); Panel_draw(panel, i == focus);
if (i < items) { if (i < items) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
mvvline(lb->y, lb->x+lb->w, ' ', lb->h+1); mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
} }
} }
} }
FunctionBar* bar = (FunctionBar*) TypedVector_get(this->fuBars, focus); FunctionBar* bar = (FunctionBar*) Vector_get(this->fuBars, focus);
if (bar) if (bar)
this->fuBar = bar; this->fuBar = bar;
if (this->fuBar) if (this->fuBar)
@ -150,7 +144,6 @@ void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) {
ch = getch(); ch = getch();
bool loop = false;
if (ch == KEY_MOUSE) { if (ch == KEY_MOUSE) {
MEVENT mevent; MEVENT mevent;
int ok = getmouse(&mevent); int ok = getmouse(&mevent);
@ -159,23 +152,21 @@ void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) {
ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x); ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x);
} else { } else {
for (int i = 0; i < this->itemCount; i++) { for (int i = 0; i < this->itemCount; i++) {
ListBox* lb = (ListBox*) TypedVector_get(this->items, i); Panel* panel = (Panel*) Vector_get(this->items, i);
if (mevent.x > lb->x && mevent.x <= lb->x+lb->w && if (mevent.x > panel->x && mevent.x <= panel->x+panel->w &&
mevent.y > lb->y && mevent.y <= lb->y+lb->h) { mevent.y > panel->y && mevent.y <= panel->y+panel->h) {
focus = i; focus = i;
lbFocus = lb; panelFocus = panel;
ListBox_setSelected(lb, mevent.y - lb->y + lb->scrollV - 1); Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
loop = true;
break; break;
} }
} }
} }
} }
} }
if (loop) continue;
if (lbFocus->eventHandler) { if (panelFocus->eventHandler) {
HandlerResult result = lbFocus->eventHandler(lbFocus, ch); HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
if (result == HANDLED) { if (result == HANDLED) {
continue; continue;
} else if (result == BREAK_LOOP) { } else if (result == BREAK_LOOP) {
@ -196,8 +187,8 @@ void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) {
tryLeft: tryLeft:
if (focus > 0) if (focus > 0)
focus--; focus--;
lbFocus = (ListBox*) TypedVector_get(this->items, focus); panelFocus = (Panel*) Vector_get(this->items, focus);
if (ListBox_getSize(lbFocus) == 0 && focus > 0) if (Panel_size(panelFocus) == 0 && focus > 0)
goto tryLeft; goto tryLeft;
break; break;
case KEY_RIGHT: case KEY_RIGHT:
@ -205,8 +196,8 @@ void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) {
tryRight: tryRight:
if (focus < this->itemCount - 1) if (focus < this->itemCount - 1)
focus++; focus++;
lbFocus = (ListBox*) TypedVector_get(this->items, focus); panelFocus = (Panel*) Vector_get(this->items, focus);
if (ListBox_getSize(lbFocus) == 0 && focus < this->itemCount - 1) if (Panel_size(panelFocus) == 0 && focus < this->itemCount - 1)
goto tryRight; goto tryRight;
break; break;
case KEY_F(10): case KEY_F(10):
@ -215,11 +206,11 @@ void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey) {
quit = true; quit = true;
continue; continue;
default: default:
ListBox_onKey(lbFocus, ch); Panel_onKey(panelFocus, ch);
break; break;
} }
} }
*lastFocus = lbFocus; *lastFocus = panelFocus;
*lastKey = ch; *lastKey = ch;
} }

View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ScreenManager #ifndef HEADER_ScreenManager
#define HEADER_ScreenManager #define HEADER_ScreenManager
@ -9,9 +9,9 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ListBox.h" #include "Panel.h"
#include "Object.h" #include "Object.h"
#include "TypedVector.h" #include "Vector.h"
#include "FunctionBar.h" #include "FunctionBar.h"
#include "debug.h" #include "debug.h"
@ -31,10 +31,10 @@ typedef struct ScreenManager_ {
int x2; int x2;
int y2; int y2;
Orientation orientation; Orientation orientation;
TypedVector* items; Vector* items;
Vector* fuBars;
int itemCount; int itemCount;
FunctionBar* fuBar; FunctionBar* fuBar;
TypedVector* fuBars;
bool owner; bool owner;
} ScreenManager; } ScreenManager;
@ -43,16 +43,14 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori
void ScreenManager_delete(ScreenManager* this); void ScreenManager_delete(ScreenManager* this);
inline int ScreenManager_size(ScreenManager* this); extern int ScreenManager_size(ScreenManager* this);
void ScreenManager_add(ScreenManager* this, ListBox* item, FunctionBar* fuBar, int size); void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size);
ListBox* ScreenManager_remove(ScreenManager* this, int index); Panel* ScreenManager_remove(ScreenManager* this, int index);
void ScreenManager_setFunctionBar(ScreenManager* this, FunctionBar* fuBar);
void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2); void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2);
void ScreenManager_run(ScreenManager* this, ListBox** lastFocus, int* lastKey); void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey);
#endif #endif

View File

@ -27,46 +27,12 @@ typedef struct 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) { void Settings_delete(Settings* this) {
free(this->userSettings); free(this->userSettings);
free(this); free(this);
} }
/* private */ static void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
char* trim = String_trim(line); char* trim = String_trim(line);
char** ids = String_split(trim, ' '); char** ids = String_split(trim, ' ');
free(trim); free(trim);
@ -77,8 +43,7 @@ void Settings_readMeters(Settings* this, char* line, HeaderSide side) {
String_freeArray(ids); String_freeArray(ids);
} }
/* private */ static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) {
void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) {
char* trim = String_trim(line); char* trim = String_trim(line);
char** ids = String_split(trim, ' '); char** ids = String_split(trim, ' ');
free(trim); free(trim);
@ -90,7 +55,7 @@ void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) {
String_freeArray(ids); String_freeArray(ids);
} }
bool Settings_read(Settings* this, char* fileName) { static bool Settings_read(Settings* this, char* fileName) {
// TODO: implement File object and make // TODO: implement File object and make
// file I/O object-oriented. // file I/O object-oriented.
FILE* fd; FILE* fd;
@ -98,7 +63,7 @@ bool Settings_read(Settings* this, char* fileName) {
if (fd == NULL) { if (fd == NULL) {
return false; return false;
} }
const int maxLine = 512; const int maxLine = 65535;
char buffer[maxLine]; char buffer[maxLine];
bool readMeters = false; bool readMeters = false;
while (!feof(fd)) { while (!feof(fd)) {
@ -139,8 +104,15 @@ bool Settings_read(Settings* this, char* fileName) {
this->pl->highlightBaseName = atoi(option[1]); this->pl->highlightBaseName = atoi(option[1]);
} else if (String_eq(option[0], "highlight_megabytes")) { } else if (String_eq(option[0], "highlight_megabytes")) {
this->pl->highlightMegabytes = atoi(option[1]); 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")) { } else if (String_eq(option[0], "header_margin")) {
this->header->margin = atoi(option[1]); this->header->margin = atoi(option[1]);
} else if (String_eq(option[0], "expand_system_time")) {
// 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], "delay")) { } else if (String_eq(option[0], "delay")) {
this->delay = atoi(option[1]); this->delay = atoi(option[1]);
} else if (String_eq(option[0], "color_scheme")) { } else if (String_eq(option[0], "color_scheme")) {
@ -195,8 +167,10 @@ bool Settings_write(Settings* this) {
fprintf(fd, "shadow_other_users=%d\n", (int) this->pl->shadowOtherUsers); fprintf(fd, "shadow_other_users=%d\n", (int) this->pl->shadowOtherUsers);
fprintf(fd, "highlight_base_name=%d\n", (int) this->pl->highlightBaseName); fprintf(fd, "highlight_base_name=%d\n", (int) this->pl->highlightBaseName);
fprintf(fd, "highlight_megabytes=%d\n", (int) this->pl->highlightMegabytes); fprintf(fd, "highlight_megabytes=%d\n", (int) this->pl->highlightMegabytes);
fprintf(fd, "highlight_threads=%d\n", (int) this->pl->highlightThreads);
fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView); fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView);
fprintf(fd, "header_margin=%d\n", (int) this->header->margin); fprintf(fd, "header_margin=%d\n", (int) this->header->margin);
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->pl->detailedCPUTime);
fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme); fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
fprintf(fd, "delay=%d\n", (int) this->delay); fprintf(fd, "delay=%d\n", (int) this->delay);
fprintf(fd, "left_meters="); fprintf(fd, "left_meters=");
@ -220,6 +194,41 @@ bool Settings_write(Settings* this) {
fprintf(fd, "right_meter_modes="); fprintf(fd, "right_meter_modes=");
for (int i = 0; i < Header_size(this->header, RIGHT_HEADER); i++) for (int i = 0; i < Header_size(this->header, RIGHT_HEADER); i++)
fprintf(fd, "%d ", Header_readMeterMode(this->header, i, RIGHT_HEADER)); fprintf(fd, "%d ", Header_readMeterMode(this->header, i, RIGHT_HEADER));
fprintf(fd, "\n");
fclose(fd); fclose(fd);
return true; return true;
} }
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;
pl->highlightThreads = false;
}
}
return this;
}

View File

@ -3,7 +3,7 @@
#ifndef HEADER_Settings #ifndef HEADER_Settings
#define HEADER_Settings #define HEADER_Settings
/* /*
htop - Settings.c htop - Settings.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -28,14 +28,10 @@ typedef struct Settings_ {
} Settings; } Settings;
Settings* Settings_new(ProcessList* pl, Header* header);
void Settings_delete(Settings* this); void Settings_delete(Settings* this);
bool Settings_read(Settings* this, char* fileName);
bool Settings_write(Settings* this); bool Settings_write(Settings* this);
Settings* Settings_new(ProcessList* pl, Header* header);
#endif #endif

View File

@ -23,30 +23,22 @@ typedef struct Signal_ {
int number; int number;
} Signal; } Signal;
extern char* SIGNAL_CLASS;
}*/ }*/
/* private property */ #ifdef DEBUG
char* SIGNAL_CLASS = "Signal"; char* SIGNAL_CLASS = "Signal";
#else
#define SIGNAL_CLASS NULL
#endif
Signal* Signal_new(char* name, int number) { static void Signal_delete(Object* cast) {
Signal* this = malloc(sizeof(Signal));
((Object*)this)->class = 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; Signal* this = (Signal*)cast;
assert (this != NULL); assert (this != NULL);
// names are string constants, so we're not deleting them. // names are string constants, so we're not deleting them.
free(this); free(this);
} }
void Signal_display(Object* cast, RichString* out) { static void Signal_display(Object* cast, RichString* out) {
Signal* this = (Signal*)cast; Signal* this = (Signal*)cast;
assert (this != NULL); assert (this != NULL);
@ -55,6 +47,16 @@ void Signal_display(Object* cast, RichString* out) {
RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer); RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer);
} }
static Signal* Signal_new(char* name, int number) {
Signal* this = malloc(sizeof(Signal));
Object_setClass(this, SIGNAL_CLASS);
((Object*)this)->display = Signal_display;
((Object*)this)->delete = Signal_delete;
this->name = name;
this->number = number;
return this;
}
int Signal_getSignalCount() { int Signal_getSignalCount() {
return SIGNAL_COUNT; return SIGNAL_COUNT;
} }

View File

@ -1,9 +1,9 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Signal #ifndef HEADER_SignalItem
#define HEADER_Signal #define HEADER_SignalItem
/* /*
htop htop - SignalItem.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -25,14 +25,12 @@ typedef struct Signal_ {
int number; int number;
} Signal; } Signal;
#ifdef DEBUG
extern char* SIGNAL_CLASS; extern char* SIGNAL_CLASS;
#else
#define SIGNAL_CLASS NULL
Signal* Signal_new(char* name, int number); #endif
void Signal_delete(Object* cast);
void Signal_display(Object* cast, RichString* out);
int Signal_getSignalCount(); int Signal_getSignalCount();

View File

@ -1,77 +0,0 @@
#include "SignalsListBox.h"
#include "ListBox.h"
#include "SignalItem.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
/*{
typedef struct SignalsListBox_ {
ListBox super;
int state;
Signal** signals;
} SignalsListBox;
}*/
SignalsListBox* SignalsListBox_new(int x, int y, int w, int h) {
SignalsListBox* this = (SignalsListBox*) malloc(sizeof(SignalsListBox));
ListBox* super = (ListBox*) this;
ListBox_init(super, x, y, w, h, SIGNAL_CLASS, true);
((Object*)this)->delete = SignalsListBox_delete;
this->signals = Signal_getSignalTable();
super->eventHandler = SignalsListBox_EventHandler;
int sigCount = Signal_getSignalCount();
for(int i = 0; i < sigCount; i++)
ListBox_set(super, i, (Object*) this->signals[i]);
SignalsListBox_reset(this);
return this;
}
void SignalsListBox_delete(Object* object) {
ListBox* super = (ListBox*) object;
SignalsListBox* this = (SignalsListBox*) object;
ListBox_done(super);
free(this->signals);
free(this);
}
void SignalsListBox_reset(SignalsListBox* this) {
ListBox* super = (ListBox*) this;
ListBox_setHeader(super, "Send signal:");
ListBox_setSelected(super, 16); // 16th item is SIGTERM
this->state = 0;
}
HandlerResult SignalsListBox_EventHandler(ListBox* super, int ch) {
SignalsListBox* this = (SignalsListBox*) super;
int size = ListBox_getSize(super);
if (ch <= 255 && isdigit(ch)) {
int signal = ch-48 + this->state;
for (int i = 0; i < size; i++)
if (((Signal*) ListBox_get(super, i))->number == signal) {
ListBox_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;
}

View File

@ -1,32 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_SignalsListBox
#define HEADER_SignalsListBox
#include "ListBox.h"
#include "SignalItem.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
typedef struct SignalsListBox_ {
ListBox super;
int state;
Signal** signals;
} SignalsListBox;
SignalsListBox* SignalsListBox_new(int x, int y, int w, int h);
void SignalsListBox_delete(Object* object);
void SignalsListBox_reset(SignalsListBox* this);
HandlerResult SignalsListBox_EventHandler(ListBox* super, int ch);
#endif

77
SignalsPanel.c Normal file
View File

@ -0,0 +1,77 @@
#include "SignalsPanel.h"
#include "Panel.h"
#include "SignalItem.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
/*{
typedef struct SignalsPanel_ {
Panel super;
int state;
Signal** signals;
} SignalsPanel;
}*/
static HandlerResult SignalsPanel_eventHandler(Panel* super, int ch) {
SignalsPanel* this = (SignalsPanel*) super;
int size = Panel_size(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;
}
static void SignalsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
SignalsPanel* this = (SignalsPanel*) object;
Panel_done(super);
free(this->signals);
free(this);
}
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h) {
SignalsPanel* this = (SignalsPanel*) malloc(sizeof(SignalsPanel));
Panel* super = (Panel*) this;
Panel_init(super, x, y, w, h, SIGNAL_CLASS, true);
((Object*)this)->delete = SignalsPanel_delete;
this->signals = Signal_getSignalTable();
super->eventHandler = SignalsPanel_eventHandler;
int sigCount = Signal_getSignalCount();
for(int i = 0; i < sigCount; i++)
Panel_set(super, i, (Object*) this->signals[i]);
SignalsPanel_reset(this);
return this;
}
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;
}

28
SignalsPanel.h Normal file
View File

@ -0,0 +1,28 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_SignalsPanel
#define HEADER_SignalsPanel
#include "Panel.h"
#include "SignalItem.h"
#include "RichString.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
typedef struct SignalsPanel_ {
Panel super;
int state;
Signal** signals;
} SignalsPanel;
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h);
void SignalsPanel_reset(SignalsPanel* this);
#endif

View File

@ -14,9 +14,9 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
inline void String_delete(char* s) { /*{
free(s); #define String_startsWith(s, match) (strstr((s), (match)) == (s))
} }*/
inline char* String_copy(char* orig) { inline char* String_copy(char* orig) {
return strdup(orig); return strdup(orig);
@ -45,54 +45,7 @@ char* String_trim(char* in) {
return out; return out;
} }
char* String_copyUpTo(char* orig, char upTo) { inline int String_eq(const char* s1, const char* s2) {
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(char* s1, char* s2) {
if (s1 == NULL || s2 == NULL) { if (s1 == NULL || s2 == NULL) {
if (s1 == NULL && s2 == NULL) if (s1 == NULL && s2 == NULL)
return 1; return 1;
@ -102,10 +55,6 @@ inline int String_eq(char* s1, char* s2) {
return (strcmp(s1, s2) == 0); return (strcmp(s1, s2) == 0);
} }
inline int String_startsWith(char* s, char* match) {
return (strstr(s, match) == s);
}
char** String_split(char* s, char sep) { char** String_split(char* s, char sep) {
const int rate = 10; const int rate = 10;
char** out = (char**) malloc(sizeof(char*) * rate); char** out = (char**) malloc(sizeof(char*) * rate);
@ -144,10 +93,6 @@ void String_freeArray(char** s) {
free(s); free(s);
} }
int String_startsWith_i(char* s, char* match) {
return (strncasecmp(s, match, strlen(match)) == 0);
}
int String_contains_i(char* s, char* match) { int String_contains_i(char* s, char* match) {
int lens = strlen(s); int lens = strlen(s);
int lenmatch = strlen(match); int lenmatch = strlen(match);
@ -158,3 +103,30 @@ int String_contains_i(char* s, char* match) {
} }
return 0; return 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] != EOF) {
match[foundCount] = line[i];
foundCount++;
}
}
}
match[foundCount] = '\0';
return((char*)strdup(match));
}

View File

@ -1,4 +1,4 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_String #ifndef HEADER_String
#define HEADER_String #define HEADER_String
@ -17,36 +17,22 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
inline void String_delete(char* s); #define String_startsWith(s, match) (strstr((s), (match)) == (s))
inline char* String_copy(char* orig); extern char* String_copy(char* orig);
char* String_cat(char* s1, char* s2); char* String_cat(char* s1, char* s2);
char* String_trim(char* in); char* String_trim(char* in);
char* String_copyUpTo(char* orig, char upTo); extern int String_eq(const char* s1, const char* s2);
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(char* s1, char* s2);
inline int String_startsWith(char* s, char* match);
char** String_split(char* s, char sep); char** String_split(char* s, char sep);
void String_freeArray(char** s); void String_freeArray(char** s);
int String_startsWith_i(char* s, char* match);
int String_contains_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 #endif

View File

@ -19,10 +19,30 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
/* private property */ int SwapMeter_attributes[] = {
static int SwapMeter_attributes[] = { SWAP }; SWAP
};
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 / 1024, (long int) this->total / 1024);
}
static 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);
}
/* private */
MeterType SwapMeter = { MeterType SwapMeter = {
.setValues = SwapMeter_setValues, .setValues = SwapMeter_setValues,
.display = SwapMeter_display, .display = SwapMeter_display,
@ -34,23 +54,3 @@ MeterType SwapMeter = {
.uiName = "Swap", .uiName = "Swap",
.caption = "Swp" .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_prune(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);
}

View File

@ -22,10 +22,8 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
extern int SwapMeter_attributes[];
extern MeterType SwapMeter;
void SwapMeter_setValues(Meter* this, char* buffer, int len);
void SwapMeter_display(Object* cast, RichString* out);
#endif #endif

20
TODO Normal file
View File

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

View File

@ -14,10 +14,28 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
/* private property */ int TasksMeter_attributes[] = {
int TasksMeter_attributes[] = { TASKS_RUNNING }; TASKS_RUNNING
};
static 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);
}
static 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");
}
/* private */
MeterType TasksMeter = { MeterType TasksMeter = {
.setValues = TasksMeter_setValues, .setValues = TasksMeter_setValues,
.display = TasksMeter_display, .display = TasksMeter_display,
@ -29,21 +47,3 @@ MeterType TasksMeter = {
.uiName = "Task counter", .uiName = "Task counter",
.caption = "Tasks: " .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_prune(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");
}

View File

@ -17,10 +17,8 @@ in the source distribution for its full text.
#include "debug.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);
#endif #endif

View File

@ -18,45 +18,42 @@ in the source distribution for its full text.
#include "ProcessList.h" #include "ProcessList.h"
#include "Process.h" #include "Process.h"
#include "ListItem.h" #include "ListItem.h"
#include "ListBox.h" #include "Panel.h"
#include "FunctionBar.h" #include "FunctionBar.h"
/*{ /*{
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; Process* process;
ListBox* display; Panel* display;
FunctionBar* bar; FunctionBar* bar;
bool tracing; bool tracing;
} TraceScreen; } TraceScreen;
}*/ }*/
/* private property */ static char* tbFunctions[] = {"AutoScroll ", "Stop Tracing ", "Done ", NULL};
static char* tbFunctions[3] = {"AutoScroll ", "Stop Tracing ", "Done "};
/* private property */ static char* tbKeys[] = {"F4", "F5", "Esc"};
static char* tbKeys[3] = {"F4", "F5", "Esc"};
/* private property */ static int tbEvents[] = {KEY_F(4), KEY_F(5), 27};
static int tbEvents[3] = {KEY_F(4), KEY_F(5), 27};
TraceScreen* TraceScreen_new(Process* process) { TraceScreen* TraceScreen_new(Process* process) {
TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen)); TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen));
this->process = process; this->process = process;
this->display = ListBox_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true); this->display = Panel_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true, ListItem_compare);
this->bar = FunctionBar_new(3, tbFunctions, tbKeys, tbEvents); this->bar = FunctionBar_new(tbFunctions, tbKeys, tbEvents);
this->tracing = true; this->tracing = true;
return this; return this;
} }
void TraceScreen_delete(TraceScreen* this) { void TraceScreen_delete(TraceScreen* this) {
ListBox_delete((Object*)this->display); Panel_delete((Object*)this->display);
FunctionBar_delete((Object*)this->bar); FunctionBar_delete((Object*)this->bar);
free(this); free(this);
} }
void TraceScreen_draw(TraceScreen* this) { static void TraceScreen_draw(TraceScreen* this) {
attrset(CRT_colors[PANEL_HEADER_FOCUS]); attrset(CRT_colors[PANEL_HEADER_FOCUS]);
mvhline(0, 0, ' ', COLS); mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm); mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
@ -77,11 +74,13 @@ void TraceScreen_run(TraceScreen* this) {
fcntl(fdpair[1], F_SETFL, O_NONBLOCK); fcntl(fdpair[1], F_SETFL, O_NONBLOCK);
sprintf(buffer, "%d", this->process->pid); sprintf(buffer, "%d", this->process->pid);
execlp("strace", "strace", "-p", buffer, NULL); execlp("strace", "strace", "-p", buffer, NULL);
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
write(fdpair[1], message, strlen(message));
exit(1); exit(1);
} }
fcntl(fdpair[0], F_SETFL, O_NONBLOCK); fcntl(fdpair[0], F_SETFL, O_NONBLOCK);
FILE* strace = fdopen(fdpair[0], "r"); FILE* strace = fdopen(fdpair[0], "r");
ListBox* lb = this->display; Panel* panel = this->display;
int fd_strace = fileno(strace); int fd_strace = fileno(strace);
TraceScreen_draw(this); TraceScreen_draw(this);
CRT_disableDelay(); CRT_disableDelay();
@ -105,31 +104,31 @@ void TraceScreen_run(TraceScreen* this) {
if (buffer[i] == '\n') { if (buffer[i] == '\n') {
buffer[i] = '\0'; buffer[i] = '\0';
if (contLine) { if (contLine) {
ListItem_append((ListItem*)ListBox_get(lb, ListItem_append((ListItem*)Panel_get(panel,
ListBox_getSize(lb)-1), line); Panel_size(panel)-1), line);
contLine = false; contLine = false;
} else { } else {
ListBox_add(lb, (Object*) ListItem_new(line, 0)); Panel_add(panel, (Object*) ListItem_new(line, 0));
} }
line = buffer+i+1; line = buffer+i+1;
} }
} }
if (line < buffer+nread) { if (line < buffer+nread) {
ListBox_add(lb, (Object*) ListItem_new(line, 0)); Panel_add(panel, (Object*) ListItem_new(line, 0));
buffer[nread] = '\0'; buffer[nread] = '\0';
contLine = true; contLine = true;
} }
if (follow) if (follow)
ListBox_setSelected(lb, ListBox_getSize(lb)-1); Panel_setSelected(panel, Panel_size(panel)-1);
ListBox_draw(lb, true); Panel_draw(panel, true);
} }
int ch = getch(); int ch = getch();
if (ch == KEY_MOUSE) { if (ch == KEY_MOUSE) {
MEVENT mevent; MEVENT mevent;
int ok = getmouse(&mevent); int ok = getmouse(&mevent);
if (ok == OK) if (ok == OK)
if (mevent.y >= lb->y && mevent.y < LINES - 1) { if (mevent.y >= panel->y && mevent.y < LINES - 1) {
ListBox_setSelected(lb, mevent.y - lb->y + lb->scrollV); Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
follow = false; follow = false;
ch = 0; ch = 0;
} if (mevent.y == LINES - 1) } if (mevent.y == LINES - 1)
@ -147,23 +146,24 @@ void TraceScreen_run(TraceScreen* this) {
case KEY_F(4): case KEY_F(4):
follow = !follow; follow = !follow;
if (follow) if (follow)
ListBox_setSelected(lb, ListBox_getSize(lb)-1); Panel_setSelected(panel, Panel_size(panel)-1);
break; break;
case 'q': case 'q':
case 27: case 27:
looping = false; looping = false;
break; break;
case KEY_RESIZE: case KEY_RESIZE:
ListBox_resize(lb, COLS, LINES-2); Panel_resize(panel, COLS, LINES-2);
TraceScreen_draw(this); TraceScreen_draw(this);
break; break;
default: default:
follow = false; follow = false;
ListBox_onKey(lb, ch); Panel_onKey(panel, ch);
} }
ListBox_draw(lb, true); Panel_draw(panel, true);
} }
kill(child, SIGTERM); kill(child, SIGTERM);
waitpid(child, NULL, 0); waitpid(child, NULL, 0);
fclose(strace); fclose(strace);
CRT_enableDelay();
} }

View File

@ -1,11 +1,13 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_TraceScreen
#define HEADER_TraceScreen
/* /*
htop - TraceScreen.h htop - TraceScreen.h
(C) 2005 Hisham H. Muhammad (C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifndef HEADER_TraceScreen
#define HEADER_TraceScreen
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
@ -13,25 +15,28 @@ in the source distribution for its full text.
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ProcessList.h" #include "ProcessList.h"
#include "ListBox.h" #include "Process.h"
#include "ListItem.h"
#include "Panel.h"
#include "FunctionBar.h" #include "FunctionBar.h"
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; Process* process;
ListBox* display; Panel* display;
FunctionBar* bar; FunctionBar* bar;
bool tracing; bool tracing;
} TraceScreen; } TraceScreen;
TraceScreen* TraceScreen_new(Process* process); TraceScreen* TraceScreen_new(Process* process);
void TraceScreen_delete(TraceScreen* this); void TraceScreen_delete(TraceScreen* this);
void TraceScreen_draw(TraceScreen* this);
void TraceScreen_run(TraceScreen* this); void TraceScreen_run(TraceScreen* this);
#endif #endif

View File

@ -1,69 +0,0 @@
/* Do not edit this file. It was automatically genarated. */
#ifndef HEADER_TypedVector
#define HEADER_TypedVector
/*
htop
(C) 2004-2006 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>
#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1
#endif
typedef void(*TypedVector_procedure)(void*);
typedef struct TypedVector_ {
Object **array;
int arraySize;
int growthRate;
int items;
char* vectorType;
bool owner;
} TypedVector;
TypedVector* TypedVector_new(char* vectorType_, bool owner, int size);
void TypedVector_delete(TypedVector* this);
void TypedVector_prune(TypedVector* this);
void TypedVector_sort(TypedVector* this);
void TypedVector_insert(TypedVector* this, int index, void* data_);
Object* TypedVector_take(TypedVector* this, int index);
Object* TypedVector_remove(TypedVector* this, int index);
void TypedVector_moveUp(TypedVector* this, int index);
void TypedVector_moveDown(TypedVector* this, int index);
void TypedVector_set(TypedVector* this, int index, void* data_);
inline Object* TypedVector_get(TypedVector* this, int index);
inline int TypedVector_size(TypedVector* this);
void TypedVector_merge(TypedVector* this, TypedVector* v2);
void TypedVector_add(TypedVector* this, void* data_);
inline int TypedVector_indexOf(TypedVector* this, void* search_);
void TypedVector_foreach(TypedVector* this, TypedVector_procedure f);
#endif

View File

@ -14,37 +14,25 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
/* private property */ int UptimeMeter_attributes[] = {
static int UptimeMeter_attributes[] = { UPTIME }; UPTIME
/* private */
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) { static void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
double uptime; double uptime;
FILE* fd = fopen(PROCDIR "/uptime", "r"); FILE* fd = fopen(PROCDIR "/uptime", "r");
fscanf(fd, "%lf", &uptime); fscanf(fd, "%lf", &uptime);
fclose(fd); fclose(fd);
int totalseconds = (int) ceil(uptime); int totalseconds = (int) ceil(uptime);
int seconds = totalseconds % 60; int seconds = totalseconds % 60;
int minutes = (totalseconds-seconds) % 3600 / 60; int minutes = (totalseconds/60) % 60;
int hours = (totalseconds-seconds-(minutes*60)) % 86400 / 3600; int hours = (totalseconds/3600) % 24;
int days = (totalseconds-seconds-(minutes*60)-(hours*3600)) / 86400; int days = (totalseconds/86400);
this->values[0] = days; this->values[0] = days;
if (days > this->total) { if (days > this->total) {
this->total = days; this->total = days;
} }
char daysbuf[10]; char daysbuf[15];
if (days > 100) { if (days > 100) {
sprintf(daysbuf, "%d days(!), ", days); sprintf(daysbuf, "%d days(!), ", days);
} else if (days > 1) { } else if (days > 1) {
@ -56,3 +44,15 @@ void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
} }
snprintf(buffer, len, "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds); snprintf(buffer, len, "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds);
} }
MeterType UptimeMeter = {
.setValues = UptimeMeter_setValues,
.display = NULL,
.mode = TEXT_METERMODE,
.items = 1,
.total = 100.0,
.attributes = UptimeMeter_attributes,
.name = "Uptime",
.uiName = "Uptime",
.caption = "Uptime: "
};

View File

@ -17,8 +17,8 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
extern int UptimeMeter_attributes[];
extern MeterType UptimeMeter;
void UptimeMeter_setValues(Meter* cast, char* buffer, int len);
#endif #endif

View File

@ -35,7 +35,7 @@ void UsersTable_delete(UsersTable* this) {
free(this); free(this);
} }
char* UsersTable_getRef(UsersTable* this, int uid) { char* UsersTable_getRef(UsersTable* this, unsigned int uid) {
char* name = (char*) (Hashtable_get(this->users, uid)); char* name = (char*) (Hashtable_get(this->users, uid));
if (name == NULL) { if (name == NULL) {
struct passwd* userData = getpwuid(uid); struct passwd* userData = getpwuid(uid);
@ -47,10 +47,6 @@ char* UsersTable_getRef(UsersTable* this, int uid) {
return 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) { inline void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData) {
Hashtable_foreach(this->users, f, userData); Hashtable_foreach(this->users, f, userData);
} }

View File

@ -1,9 +1,9 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_UsersTable #ifndef HEADER_UsersTable
#define HEADER_UsersTable #define HEADER_UsersTable
/* /*
htop htop - UsersTable.h
(C) 2004-2006 Hisham H. Muhammad (C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
@ -20,10 +20,6 @@ in the source distribution for its full text.
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifndef SYSCONFDIR
#define SYSCONFDIR "/etc"
#endif
typedef struct UsersTable_ { typedef struct UsersTable_ {
Hashtable* users; Hashtable* users;
} UsersTable; } UsersTable;
@ -32,10 +28,8 @@ UsersTable* UsersTable_new();
void UsersTable_delete(UsersTable* this); void UsersTable_delete(UsersTable* this);
char* UsersTable_getRef(UsersTable* this, int uid); char* UsersTable_getRef(UsersTable* this, unsigned int uid);
inline int UsersTable_size(UsersTable* this); extern void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData);
void UsersTable_foreach(UsersTable*, Hashtable_PairFunction, void*);
#endif #endif

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