87 Commits

Author SHA1 Message Date
a4f4ef5b63 Tag 3.0.0beta5 2018-08-24 22:55:24 -03:00
8c43218aa0 Introduce screen tabs 2018-08-24 22:53:07 -03:00
e77a16f4ae Linux: proper sorting of CMAJFILT and CMINFILT 2018-08-24 22:45:36 -03:00
a49853543e Change to previous screen using Shift-Tab 2018-08-24 19:30:54 -03:00
28a5859fe8 Settings: fix storage of screens in htoprc 2018-08-24 18:39:00 -03:00
0939e5cb41 Settings: fix default and storage of sort keys 2018-08-24 18:39:00 -03:00
e1c2dc56fd Linux: fix CPU count 2018-08-24 18:39:00 -03:00
e9f95da559 Linux: remove warnings of unused variables 2018-08-24 18:39:00 -03:00
5a0a4e1adb Improve Catalan translation for desktop file (#828) 2018-08-24 18:39:00 -03:00
f3b47c46e6 Improve htop.desktop file (#609)
- sort entries according to the spec
- add to the `Monitor` category
2018-08-24 16:01:50 -03:00
34b147e14e Linux: add process->starttime and use it for STARTTIME column (#700)
this way a remount of /proc will not reset starttimes
and we can also see startup times for processes started before the mount
of /proc

also record btime (boot time in seconds since epoch) as Linux semi-global
2018-08-24 16:01:43 -03:00
03e0a73d5b OpenBSD: make the STARTTIME column display correctly (#815) 2018-08-24 16:01:38 -03:00
794419e6c5 OpenBSD: add environment reading support (#819) 2018-08-24 16:01:31 -03:00
7ec5312974 Fix process name updates for shorter strings (#812)
When a process name changes from a long string to a short string,
truncate instead of just overwriting the beginning.
2018-08-24 16:01:25 -03:00
af92f0b8d6 Fix virtualization color in help screen
Closes #785.
2018-08-24 16:01:19 -03:00
22e9d09723 Unstage/gitignore INSTALL since it's regenerated by autogen.sh
As noted by @marcelpaulo. I've had ugly diffs that fiddled with
this file in the past, so it's good to see it gone.

Closes #800.
2018-08-24 16:01:12 -03:00
fda1475a10 Mention the "c" key (tag subtree) in the man
This was reported by @agguser.
2018-08-24 16:01:06 -03:00
ebf3cff1ac Disable 'make dist' when pkg.m4 is unused in configure
This would prevent a careless future package maintainer from creating a
release tarball with a defective configure script. :)

Also, add a warning in the autogen.sh phase if pkg.m4 is unused.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-08-24 16:00:59 -03:00
7bbb3600fc fix option string
This broke with commit db05ba6106.
2018-08-24 16:00:52 -03:00
4092c90bc3 Update ChangeLog 2018-08-24 16:00:23 -03:00
7742e17cc0 Add tree view flag to man page (#777) 2018-08-24 16:00:01 -03:00
2dffee8de9 Require pkg-config as an optional build dependency on Linux (#775)
With this commit:

* if pkgconfig is installed, it will expand the code inside the shell if, adding the pkgconfig-based tests for the dependencies of Linux delay accounting.
* if pkgconfig is not installed, it will add an error message inside the test of Linux delay accounting, telling the user to install pkgconfig and rebuild the configure script if they want to use Linux delay accounting.

The end result is:

* people running Linux
  * will not need pkgconfig when not using delay accounting
  * will need pkgconfig when using delay accounting
    * if they don't have it
      * they are told by configure they need to install it and re-run autogen.sh when running from Git
      * they are told by configure they need to install it and re-run configure when running from the tarball
* people not running Linux
  * will never need pkgconfig

...and in none of the above scenarios the generated configure script produces unexpanded macros for users checking out the sources from Git.
2018-08-24 15:59:40 -03:00
791aae87c4 MakeHeader.py: Fix for non-utf8 environments (#770)
Header creation fails with non-utf8 locale and python3.
Simply set LC_ALL="C" and use python3 to reproduce the issue.

env LC_ALL="C" ./scripts/MakeHeader.py MetersPanel.c
Traceback (most recent call last):
  File "./scripts/MakeHeader.py", line 32, in <module>
    for line in file.readlines():
  File "/usr/lib64/python3.5/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 956: ordinal not in range(128)

This changes is python2 and python3 compatible

cStringIO.StringIO module is removed because it is not able to accept unicode strings
https://docs.python.org/2/library/stringio.html#cStringIO.StringIO
2018-08-24 15:58:12 -03:00
505fa6b517 Solaris: grammatical whoops in configure.ac 2018-05-22 23:17:30 -03:00
f94c54eb5a Solaris: add check for missing err.h 2018-05-22 23:17:30 -03:00
9710ce6c08 Solaris: Make last change to Platform.h persistent by adding to Platform.c 2018-05-22 23:17:30 -03:00
f78f658eed dragonflybsd, freebsd, openbsd: fixes for htop 3.0 branch 2018-04-10 10:22:44 -03:00
b8bfe60d2b Solaris: fix build on htop 3.0 branch 2018-04-10 10:21:29 -03:00
5c6d7cca3e Bump version to 3.0.0beta4 2018-04-06 12:43:24 -03:00
6fe06fb7e5 Portability: make list of default screens per-platform 2018-04-06 12:41:36 -03:00
657836a2ae Minor style fixes. 2018-04-06 12:40:51 -03:00
63e1417b8c Update some field accesses to new structures 2018-04-06 12:34:57 -03:00
9b4bdfcb3e Add -t command-line flag for tree view 2018-04-06 11:14:09 -03:00
7a71f9cf32 macOS: fix the switched version test (#772) 2018-04-06 11:14:09 -03:00
c91b0938d5 Solaris: update proc state letters to reflect Solaris usage 2018-04-06 11:14:09 -03:00
4f934c977d Solaris: bump copyright in Platform.{c,h} 2018-04-06 11:14:09 -03:00
d1696b5d5d Solaris: fix a memory leak caused by calling ProcessList_getProcess twice for each LWP 2018-04-06 11:14:09 -03:00
beb47cbb12 Solaris: Implement process environment listing 2018-04-06 11:14:09 -03:00
677cac9fab Solaris: add placeholder message about environment listing 2018-04-06 11:14:09 -03:00
6790e004cd Solaris: showing a dash for the top-level process is no longer necessary 2018-04-06 11:14:09 -03:00
8677162836 Solaris: add warning about proc_walk_f callback function 2018-04-06 11:14:09 -03:00
475798e8ab Solaris: condense separate process vs lwp handling down to a single workflow 2018-04-06 11:14:09 -03:00
7689c5c3b7 Solaris: get completely out of the file handling business using libproc 2018-04-06 11:14:09 -03:00
c2ab3ac422 Solaris: Condense conditional blocks for new vs old LWPs and procs 2018-04-06 11:14:09 -03:00
61bb649e0a Solaris: remove unneeded accumulators for process and thread counting 2018-04-06 11:14:09 -03:00
b8ec1c0337 Solaris: Assorted post-LWP code cleanup 2018-04-06 11:14:09 -03:00
499af738e7 Solaris: Implement kernel thread counting 2018-04-06 11:14:09 -03:00
416ef48a62 Solaris: If a process has a running LWP, then the process is by definition running 2018-04-06 11:14:09 -03:00
b9e0da9200 Collapse current subtree pressing Backspace 2018-04-06 11:14:09 -03:00
509303323f Solaris: Implement LWP enumeration (#768)
Squashed the following commits:

* Solaris: Get LWP enumeration working
* Solaris: Make showing and hiding of kernel threads behave
* Solaris: remove usage of lwpstatus that is no longer needed
* Solaris: no discrete access to parent proc structure needed
* Solaris: Restore runtime MaxPid detection after LWP changes
* Solaris: Workaround virtual PID signal issue by shadowing kill() with a macro
* Solaris: Fix unintention double-shifting of virtual PID for LWP enumeration
* Solaris: Add LWPID to default display since LWP enumeration is also default
* Solaris: use PAGE_SIZE_KB from Process.h instead of custom definition
* Solaris: stop LWP enumeration at 1023 LWPs per proc since that is all we can handle in the virtual PID
2018-04-06 11:14:09 -03:00
421a31d6f1 OpenBSD: read Battery data
Signed-off-by: Hisham Muhammad <hisham@gobolinux.org>
2018-04-06 11:14:09 -03:00
d4c4c02b97 macOS: keep scanning thread for versions before High Sierra (#728)
Keep scanning threads for versions before High Sierra 13.0.0 and after 13.3.0.
2018-04-06 11:14:09 -03:00
1ef20d1f14 Solaris: Fix virt and resident memory sizes. Was using KiB, needed pages. 2018-04-06 11:14:09 -03:00
1ab5afa1fe New makefile targets to rebuild and clean htop headers.
`make htop-headers` will regenerate all '.h' headers in htop source for
all platforms.
`make clean-htop-headers` will delete all generated htop headers.

Because of the introduction of these two targets, I slightly changed
the style of platform-specific portions of makefile rules.
Please comment if you accept such a style, or need me to revert to old
style.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-04-06 11:14:04 -03:00
00d1fb019a Linux: change how kernel threads are detected
Use the same method that ps and top use to determine if a
process is a kernel thread on Linux: check if cmdline is empty.

Thanks to @wangqr's investigation reported here:
https://github.com/hishamhm/htop/issues/761#issuecomment-375306069

Fixes #761.
2018-04-06 11:13:30 -03:00
dd175b6881 Fix overflow for signals >= 100.
Thanks to @gzip4 for tracking this down.

Closes #764.
2018-04-06 11:13:30 -03:00
7ad9701a12 strace: increase string length 2018-04-06 11:13:30 -03:00
881fe9631a Solaris: code indentation fix 2018-04-06 11:13:30 -03:00
0de77c7075 Solaris: enough changes made to justify a copyright bump to 2018 2018-04-06 11:13:30 -03:00
0f71db9d82 Solaris: fix memory allocation for usernames (some empty usernames in 32-bit builds) 2018-04-06 11:13:30 -03:00
da4010783e Solaris: fix malloc() / free() issues with zone name handling 2018-04-06 11:13:30 -03:00
3f7622a302 Solaris: Link against libmalloc to fix various crashes 2018-04-06 11:13:30 -03:00
df5d81a881 Solaris: Import backtrace-on-abort from Linux, with minor modification for Solaris 2018-04-06 11:13:30 -03:00
6c2b3b546d Use fork/exec instead of popen to run lsof (#757)
Fixes #675
2018-04-06 11:13:30 -03:00
f48f5a10ca Use AM_CFLAGS and AM_LDFLAGS in Makefile.am (#760)
This reduces generated Makefile.in size by 74%.
(217319 bytes -> 56326 bytes)

Automake considers that <prog>_CFLAGS and <prog>_LDFLAGS are
program-specific build rules, and when such are specified, Automake
will generate additional code just to avoid the "generic" and
package-wide AM_CFLAGS or AM_LDFLAGS. (Especially for <prog>_CFLAGS,
Automake will rename generated object files to become "prog-foo.o" and
such, and it's _a lot_ of code to achieve this in Makefile.)

There's no reason for htop to rename intermediate object files. It's
better to make things simpler.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-04-06 11:13:30 -03:00
1aa23925c9 Import Solaris support (#741)
This commit adds support for Solaris, squashed from PR #741:

Summary of additions:

* Initial setup of Solaris platform directory
* Add Solaris platform into autoconf template
* Uptime and load averages
* Add dependency on libkstat
* Basic process listing
* Zone name display
* CPU detection
* Per-process memory and CPU usage parsed correctly
* Uses sysconf to discover number of CPUs, instead of more complex libkstat code
* Simple memory display working
* Reduce repetitive calls to the PAGE_SIZE macro when reading memory info
* Add Project, Contract, Task, and Pool into process properties
* Use system major()/minor() implementations and remove extraneous definition of mkdev()
* Get the STARTTIME column working properly, using the Linux implementation as a guide
2018-04-06 11:13:30 -03:00
2e1f56d934 Changed type of some integer variables to avoid overflows 2018-03-16 12:01:24 -03:00
6ee99566cd Bump version to 3.0.0beta3 2018-02-26 20:13:09 -03:00
dc6bb069f0 Update generated header 2018-02-26 20:13:09 -03:00
0169577019 Fix inttypes.h header 2018-02-26 20:13:09 -03:00
0e38be9ee7 Darwin: expose LAST_PROCESSFIELD like the other platforms 2018-02-26 20:13:09 -03:00
8e6c1e1bac Add more default screens 2018-02-26 20:13:09 -03:00
709619800f Only compute counters is process is shown 2018-02-26 20:13:09 -03:00
a72439c9b7 Implemented various performance counters 2018-02-26 20:13:09 -03:00
61e94c1b5b Add IPC performance counter for Linux 2018-02-26 20:13:09 -03:00
b9f5892593 Add perf counter object 2018-02-26 20:13:09 -03:00
267d03b6d8 configure.ac: add --enable-perfcounters 2018-02-26 20:13:09 -03:00
3b819daf82 Set default sort keys in default screens 2018-02-26 20:13:09 -03:00
d9f8cdf0a6 Add make symbols target 2018-02-26 20:13:09 -03:00
59982a188c Store .sort_key as a string 2018-02-26 20:13:09 -03:00
0800424fe6 Match iotop's screen configuration 2018-02-26 20:13:09 -03:00
b4a8f048d1 Use screen's flags when reading process data 2018-02-26 20:13:09 -03:00
2df1f61d77 Screens: Fix "New Screen" option 2018-02-26 20:13:09 -03:00
e6c98b6e8e htoprc: store screen 0's setup for improved compatibility 2018-02-26 20:13:09 -03:00
b815e4c7a3 Add support for multiple screens, switchable using Tab 2018-02-26 20:13:09 -03:00
4791050cea Begin add supporting for multiple screens 2018-02-26 20:13:09 -03:00
1edcfad874 Move responsibility for cursor placement to Panels 2018-02-26 20:13:09 -03:00
192 changed files with 5121 additions and 3124 deletions

View File

@ -14,4 +14,3 @@ charset = utf-8
[*.{c,h}] [*.{c,h}]
indent_style = space indent_style = space
indent_size = 3 indent_size = 3
trim_trailing_whitespace = true

View File

@ -1,63 +0,0 @@
name: CI
on: [ push, pull_request ]
jobs:
build-ubuntu-latest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install libncursesw5-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror
- name: Build
run: make
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror
build-ubuntu-clang-latest:
runs-on: ubuntu-latest
env:
CC: clang-10
steps:
- uses: actions/checkout@v2
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' -y
sudo apt-get update -q
- name: Install Dependencies
run: sudo apt-get install clang-10 libncursesw5-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror
- name: Build
run: make
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror
build-ubuntu-latest-full-featured:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror --enable-openvz --enable-cgroup --enable-vserver --enable-ancient-vserver --enable-taskstats --enable-unicode --enable-linux-affinity --enable-hwloc --enable-setuid --enable-delayacct
- name: Build
run: make
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-cgroup --enable-vserver --enable-ancient-vserver --enable-taskstats --enable-unicode --enable-linux-affinity --enable-hwloc --enable-setuid --enable-delayacct'
whitespace_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: check-whitespaces
run: git diff-tree --check $(git hash-object -t tree /dev/null) HEAD

View File

@ -5,7 +5,6 @@ compiler:
- gcc - gcc
os: os:
- freebsd
- linux - linux
- osx - osx

154
Action.c
View File

@ -26,11 +26,44 @@ in the source distribution for its full text.
#include <math.h> #include <math.h>
#include <pwd.h> #include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess) { /*{
#include "IncSet.h"
#include "Settings.h"
#include "Header.h"
#include "UsersTable.h"
#include "ProcessList.h"
#include "Panel.h"
typedef enum {
HTOP_OK = 0x00,
HTOP_REFRESH = 0x01,
HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH
HTOP_SAVE_SETTINGS = 0x04,
HTOP_KEEP_FOLLOWING = 0x08,
HTOP_QUIT = 0x10,
HTOP_REDRAW_BAR = 0x20,
HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH
} Htop_Reaction;
typedef Htop_Reaction (*Htop_Action)();
typedef struct State_ {
Settings* settings;
UsersTable* ut;
ProcessList* pl;
Panel* panel;
Header* header;
} State;
}*/
Object* Action_pickFromVector(State* st, Panel* list, int x) {
Panel* panel = st->panel; Panel* panel = st->panel;
Header* header = st->header; Header* header = st->header;
Settings* settings = st->settings; Settings* settings = st->settings;
@ -43,12 +76,12 @@ Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess)
Panel* panelFocus; Panel* panelFocus;
int ch; int ch;
bool unfollow = false; bool unfollow = false;
int pid = followProcess ? MainPanel_selectedPid((MainPanel*)panel) : -1; int pid = MainPanel_selectedPid((MainPanel*)panel);
if (followProcess && header->pl->following == -1) { if (header->pl->following == -1) {
header->pl->following = pid; header->pl->following = pid;
unfollow = true; unfollow = true;
} }
ScreenManager_run(scr, &panelFocus, &ch); ScreenManager_run(scr, &panelFocus, &ch, NULL);
if (unfollow) { if (unfollow) {
header->pl->following = -1; header->pl->following = -1;
} }
@ -56,16 +89,11 @@ Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess)
Panel_move(panel, 0, y); Panel_move(panel, 0, y);
Panel_resize(panel, COLS, LINES-y-1); Panel_resize(panel, COLS, LINES-y-1);
if (panelFocus == list && ch == 13) { if (panelFocus == list && ch == 13) {
if (followProcess) {
Process* selected = (Process*)Panel_getSelected(panel); Process* selected = (Process*)Panel_getSelected(panel);
if (selected && selected->pid == pid) if (selected && selected->pid == pid)
return Panel_getSelected(list); return Panel_getSelected(list);
else else
beep(); beep();
} else {
return Panel_getSelected(list);
}
} }
return NULL; return NULL;
} }
@ -79,7 +107,7 @@ static void Action_runSetup(Settings* settings, const Header* header, ProcessLis
CategoriesPanel_makeMetersPage(panelCategories); CategoriesPanel_makeMetersPage(panelCategories);
Panel* panelFocus; Panel* panelFocus;
int ch; int ch;
ScreenManager_run(scr, &panelFocus, &ch); ScreenManager_run(scr, &panelFocus, &ch, "Setup");
ScreenManager_delete(scr); ScreenManager_delete(scr);
if (settings->changed) { if (settings->changed) {
Header_writeBackToSettings(header); Header_writeBackToSettings(header);
@ -144,9 +172,10 @@ static bool collapseIntoParent(Panel* panel) {
} }
Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) { Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
settings->sortKey = sortKey; ScreenSettings* ss = settings->ss;
settings->direction = 1; ss->sortKey = sortKey;
settings->treeView = false; ss->direction = 1;
ss->treeView = false;
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING; return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
} }
@ -154,15 +183,16 @@ static Htop_Reaction sortBy(State* st) {
Htop_Reaction reaction = HTOP_OK; Htop_Reaction reaction = HTOP_OK;
Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Sort ", "Cancel ")); Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Sort ", "Cancel "));
Panel_setHeader(sortPanel, "Sort by"); Panel_setHeader(sortPanel, "Sort by");
ProcessField* fields = st->settings->fields; ScreenSettings* ss = st->settings->ss;
ProcessField* fields = ss->fields;
for (int i = 0; fields[i]; i++) { for (int i = 0; fields[i]; i++) {
char* name = String_trim(Process_fields[fields[i]].name); char* name = String_trim(Process_fields[fields[i]].name);
Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i])); Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
if (fields[i] == st->settings->sortKey) if (fields[i] == ss->sortKey)
Panel_setSelected(sortPanel, i); Panel_setSelected(sortPanel, i);
free(name); free(name);
} }
ListItem* field = (ListItem*) Action_pickFromVector(st, sortPanel, 15, false); ListItem* field = (ListItem*) Action_pickFromVector(st, sortPanel, 15);
if (field) { if (field) {
reaction |= Action_setSortKey(st->settings, field->key); reaction |= Action_setSortKey(st->settings, field->key);
} }
@ -207,8 +237,9 @@ static Htop_Reaction actionToggleProgramPath(State* st) {
} }
static Htop_Reaction actionToggleTreeView(State* st) { static Htop_Reaction actionToggleTreeView(State* st) {
st->settings->treeView = !st->settings->treeView; ScreenSettings* ss = st->settings->ss;
if (st->settings->treeView) st->settings->direction = 1; ss->treeView = !ss->treeView;
if (ss->treeView) ss->direction = 1;
ProcessList_expandTree(st->pl); ProcessList_expandTree(st->pl);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
} }
@ -221,21 +252,10 @@ static Htop_Reaction actionIncFilter(State* st) {
} }
static Htop_Reaction actionIncSearch(State* st) { static Htop_Reaction actionIncSearch(State* st) {
IncSet_reset(((MainPanel*)st->panel)->inc, INC_SEARCH);
IncSet_activate(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel); IncSet_activate(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING; return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
} }
static Htop_Reaction actionIncNext(State* st) {
IncSet_next(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionIncPrev(State* st) {
IncSet_prev(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionHigherPriority(State* st) { static Htop_Reaction actionHigherPriority(State* st) {
bool changed = changePriority((MainPanel*)st->panel, -1); bool changed = changePriority((MainPanel*)st->panel, -1);
return changed ? HTOP_REFRESH : HTOP_OK; return changed ? HTOP_REFRESH : HTOP_OK;
@ -247,7 +267,7 @@ static Htop_Reaction actionLowerPriority(State* st) {
} }
static Htop_Reaction actionInvertSortOrder(State* st) { static Htop_Reaction actionInvertSortOrder(State* st) {
Settings_invertSortOrder(st->settings); ScreenSettings_invertSortOrder(st->settings->ss);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS; return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
} }
@ -261,7 +281,7 @@ static Htop_Reaction actionExpandOrCollapse(State* st) {
} }
static Htop_Reaction actionCollapseIntoParent(State* st) { static Htop_Reaction actionCollapseIntoParent(State* st) {
if (!st->settings->treeView) { if (!st->settings->ss->treeView) {
return HTOP_OK; return HTOP_OK;
} }
bool changed = collapseIntoParent(st->panel); bool changed = collapseIntoParent(st->panel);
@ -269,13 +289,52 @@ static Htop_Reaction actionCollapseIntoParent(State* st) {
} }
static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) { static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) {
return st->settings->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st); return st->settings->ss->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st);
} }
static Htop_Reaction actionQuit() { static Htop_Reaction actionQuit() {
return HTOP_QUIT; return HTOP_QUIT;
} }
static Htop_Reaction actionNextScreen(State* st) {
Settings* settings = st->settings;
settings->ssIndex++;
if (settings->ssIndex == settings->nScreens) {
settings->ssIndex = 0;
}
settings->ss = settings->screens[settings->ssIndex];
return HTOP_REFRESH;
}
static Htop_Reaction actionPrevScreen(State* st) {
Settings* settings = st->settings;
if (settings->ssIndex == 0) {
settings->ssIndex = settings->nScreens - 1;
} else {
settings->ssIndex--;
}
settings->ss = settings->screens[settings->ssIndex];
return HTOP_REFRESH;
}
Htop_Reaction Action_setScreenTab(Settings* settings, int x) {
int s = 2;
for (unsigned int i = 0; i < settings->nScreens; i++) {
if (x < s) {
return 0;
}
const char* name = settings->screens[i]->name;
int len = strlen(name);
if (x <= s + len + 1) {
settings->ssIndex = i;
settings->ss = settings->screens[i];
return HTOP_REFRESH;
}
s += len + 3;
}
return 0;
}
static Htop_Reaction actionSetAffinity(State* st) { static Htop_Reaction actionSetAffinity(State* st) {
if (st->pl->cpuCount == 1) if (st->pl->cpuCount == 1)
return HTOP_OK; return HTOP_OK;
@ -284,19 +343,17 @@ static Htop_Reaction actionSetAffinity(State* st) {
Process* p = (Process*) Panel_getSelected(panel); Process* p = (Process*) Panel_getSelected(panel);
if (!p) return HTOP_OK; if (!p) return HTOP_OK;
Affinity* affinity1 = Affinity_get(p, st->pl); Affinity* affinity = Affinity_get(p, st->pl);
if (!affinity1) return HTOP_OK; if (!affinity) return HTOP_OK;
int width; Panel* affinityPanel = AffinityPanel_new(st->pl, affinity);
Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width); Affinity_delete(affinity);
width += 1; /* we add a gap between the panels */
Affinity_delete(affinity1);
void* set = Action_pickFromVector(st, affinityPanel, width, true); void* set = Action_pickFromVector(st, affinityPanel, 15);
if (set) { if (set) {
Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl); Affinity* affinity = AffinityPanel_getAffinity(affinityPanel, st->pl);
bool ok = MainPanel_foreachProcess((MainPanel*)panel, (MainPanel_ForeachProcessFn) Affinity_set, (Arg){ .v = affinity2 }, NULL); bool ok = MainPanel_foreachProcess((MainPanel*)panel, (MainPanel_ForeachProcessFn) Affinity_set, (Arg){ .v = affinity }, NULL);
if (!ok) beep(); if (!ok) beep();
Affinity_delete(affinity2); Affinity_delete(affinity);
} }
Panel_delete((Object*)affinityPanel); Panel_delete((Object*)affinityPanel);
#endif #endif
@ -305,7 +362,7 @@ static Htop_Reaction actionSetAffinity(State* st) {
static Htop_Reaction actionKill(State* st) { static Htop_Reaction actionKill(State* st) {
Panel* signalsPanel = (Panel*) SignalsPanel_new(); Panel* signalsPanel = (Panel*) SignalsPanel_new();
ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 15, true); ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 15);
if (sgn) { if (sgn) {
if (sgn->key != 0) { if (sgn->key != 0) {
Panel_setHeader(st->panel, "Sending..."); Panel_setHeader(st->panel, "Sending...");
@ -326,7 +383,7 @@ static Htop_Reaction actionFilterByUser(State* st) {
Vector_insertionSort(usersPanel->items); Vector_insertionSort(usersPanel->items);
ListItem* allUsers = ListItem_new("All users", -1); ListItem* allUsers = ListItem_new("All users", -1);
Panel_insert(usersPanel, 0, (Object*) allUsers); Panel_insert(usersPanel, 0, (Object*) allUsers);
ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 20, false); ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 20);
if (picked) { if (picked) {
if (picked == allUsers) { if (picked == allUsers) {
st->pl->userId = -1; st->pl->userId = -1;
@ -449,7 +506,7 @@ static Htop_Reaction actionHelp(State* st) {
if (settings->detailedCPUTime) { if (settings->detailedCPUTime) {
addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/"); addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/");
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); addattrstr(CRT_colors[CPU_KERNEL], "kernel"); addstr("/");
addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/"); addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/");
addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/"); addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/");
addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/"); addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/");
@ -459,7 +516,7 @@ static Htop_Reaction actionHelp(State* st) {
} else { } else {
addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/"); addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/");
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); addattrstr(CRT_colors[CPU_KERNEL], "kernel"); addstr("/");
addattrstr(CRT_colors[CPU_GUEST], "virtualiz"); addattrstr(CRT_colors[CPU_GUEST], "virtualiz");
addattrstr(CRT_colors[BAR_SHADOW], " used%"); addattrstr(CRT_colors[BAR_SHADOW], " used%");
} }
@ -545,8 +602,6 @@ void Action_setBindings(Htop_Action* keys) {
keys['\\'] = actionIncFilter; keys['\\'] = actionIncFilter;
keys[KEY_F(3)] = actionIncSearch; keys[KEY_F(3)] = actionIncSearch;
keys['/'] = actionIncSearch; keys['/'] = actionIncSearch;
keys['n'] = actionIncNext;
keys['N'] = actionIncPrev;
keys[']'] = actionHigherPriority; keys[']'] = actionHigherPriority;
keys[KEY_F(7)] = actionHigherPriority; keys[KEY_F(7)] = actionHigherPriority;
@ -584,4 +639,7 @@ void Action_setBindings(Htop_Action* keys) {
keys['U'] = actionUntagAll; keys['U'] = actionUntagAll;
keys['c'] = actionTagAllChildren; keys['c'] = actionTagAllChildren;
keys['e'] = actionShowEnvScreen; keys['e'] = actionShowEnvScreen;
keys['\t'] = actionNextScreen;
keys[KEY_SHIFT_TAB] = actionPrevScreen;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Action #ifndef HEADER_Action
#define HEADER_Action #define HEADER_Action
/* /*
@ -7,11 +9,13 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Header.h"
#include "Panel.h" #include "IncSet.h"
#include "ProcessList.h"
#include "Settings.h" #include "Settings.h"
#include "Header.h"
#include "UsersTable.h" #include "UsersTable.h"
#include "ProcessList.h"
#include "Panel.h"
typedef enum { typedef enum {
HTOP_OK = 0x00, HTOP_OK = 0x00,
@ -34,14 +38,23 @@ typedef struct State_ {
Header* header; Header* header;
} State; } State;
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess);
Object* Action_pickFromVector(State* st, Panel* list, int x);
// ----------------------------------------
bool Action_setUserOnly(const char* userName, uid_t* userId); bool Action_setUserOnly(const char* userName, uid_t* userId);
Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey); Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey);
// ----------------------------------------
Htop_Reaction Action_setScreenTab(Settings* settings, int x);
Htop_Reaction Action_follow(State* st); Htop_Reaction Action_follow(State* st);
void Action_setBindings(Htop_Action* keys); void Action_setBindings(Htop_Action* keys);
#endif #endif

View File

@ -1,7 +1,6 @@
/* /*
htop - Affinity.c htop - Affinity.c
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2011 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
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,6 +20,18 @@ in the source distribution for its full text.
#include <sched.h> #include <sched.h>
#endif #endif
/*{
#include "Process.h"
#include "ProcessList.h"
typedef struct Affinity_ {
ProcessList* pl;
int size;
int used;
int* cpus;
} Affinity;
}*/
Affinity* Affinity_new(ProcessList* pl) { Affinity* Affinity_new(ProcessList* pl) {
Affinity* this = xCalloc(1, sizeof(Affinity)); Affinity* this = xCalloc(1, sizeof(Affinity));
@ -68,8 +79,7 @@ Affinity* Affinity_get(Process* proc, ProcessList* pl) {
return affinity; return affinity;
} }
bool Affinity_set(Process* proc, Arg arg) { bool Affinity_set(Process* proc, Affinity* this) {
Affinity *this = arg.v;
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
for (int i = 0; i < this->used; i++) { for (int i = 0; i < this->used; i++) {
hwloc_bitmap_set(cpuset, this->cpus[i]); hwloc_bitmap_set(cpuset, this->cpus[i]);
@ -93,8 +103,7 @@ Affinity* Affinity_get(Process* proc, ProcessList* pl) {
return affinity; return affinity;
} }
bool Affinity_set(Process* proc, Arg arg) { bool Affinity_set(Process* proc, Affinity* this) {
Affinity *this = arg.v;
cpu_set_t cpuset; cpu_set_t cpuset;
CPU_ZERO(&cpuset); CPU_ZERO(&cpuset);
for (int i = 0; i < this->used; i++) { for (int i = 0; i < this->used; i++) {

View File

@ -1,13 +1,23 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Affinity #ifndef HEADER_Affinity
#define HEADER_Affinity #define HEADER_Affinity
/* /*
htop - Affinity.h htop - Affinity.h
(C) 2004-2011 Hisham H. Muhammad (C) 2004-2011 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifdef HAVE_LIBHWLOC
#if __linux__
#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD
#else
#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS
#endif
#elif HAVE_LINUX_AFFINITY
#endif
#include "Process.h" #include "Process.h"
#include "ProcessList.h" #include "ProcessList.h"
@ -18,17 +28,24 @@ typedef struct Affinity_ {
int* cpus; int* cpus;
} Affinity; } Affinity;
Affinity* Affinity_new(ProcessList* pl); Affinity* Affinity_new(ProcessList* pl);
void Affinity_delete(Affinity* this); void Affinity_delete(Affinity* this);
void Affinity_add(Affinity* this, int id); void Affinity_add(Affinity* this, int id);
#if defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY) #ifdef HAVE_LIBHWLOC
Affinity* Affinity_get(Process* proc, ProcessList* pl); Affinity* Affinity_get(Process* proc, ProcessList* pl);
bool Affinity_set(Process* proc, Arg arg); bool Affinity_set(Process* proc, Affinity* this);
#elif HAVE_LINUX_AFFINITY
Affinity* Affinity_get(Process* proc, ProcessList* pl);
bool Affinity_set(Process* proc, Affinity* this);
#endif #endif

View File

@ -8,411 +8,69 @@ in the source distribution for its full text.
#include "AffinityPanel.h" #include "AffinityPanel.h"
#include "CRT.h" #include "CRT.h"
#include "Vector.h" #include "CheckItem.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#ifdef HAVE_LIBHWLOC /*{
#include <hwloc.h> #include "Panel.h"
#endif #include "Affinity.h"
#include "ProcessList.h"
typedef struct MaskItem_ { #include "ListItem.h"
Object super; }*/
const char* text;
const char* indent; /* used also as an condition whether this is a tree node */
int value; /* tri-state: 0 - off, 1 - some set, 2 - all set */
int sub_tree; /* tri-state: 0 - no sub-tree, 1 - open sub-tree, 2 - closed sub-tree */
Vector *children;
#ifdef HAVE_LIBHWLOC
bool ownCpuset;
hwloc_bitmap_t cpuset;
#else
int cpu;
#endif
} MaskItem;
static void MaskItem_delete(Object* cast) {
MaskItem* this = (MaskItem*) cast;
free((void*)this->text);
if (this->indent)
free((void*)this->indent);
Vector_delete(this->children);
#ifdef HAVE_LIBHWLOC
if (this->ownCpuset)
hwloc_bitmap_free(this->cpuset);
#endif
free(this);
}
static void MaskItem_display(Object* cast, RichString* out) {
MaskItem* this = (MaskItem*)cast;
assert (this != NULL);
RichString_append(out, CRT_colors[CHECK_BOX], "[");
if (this->value == 2)
RichString_append(out, CRT_colors[CHECK_MARK], "x");
else if (this->value == 1)
RichString_append(out, CRT_colors[CHECK_MARK], "o");
else
RichString_append(out, CRT_colors[CHECK_MARK], " ");
RichString_append(out, CRT_colors[CHECK_BOX], "]");
RichString_append(out, CRT_colors[CHECK_TEXT], " ");
if (this->indent) {
RichString_append(out, CRT_colors[PROCESS_TREE], this->indent);
RichString_append(out, CRT_colors[PROCESS_TREE],
this->sub_tree == 2
? CRT_treeStr[TREE_STR_OPEN]
: CRT_treeStr[TREE_STR_SHUT]);
RichString_append(out, CRT_colors[CHECK_TEXT], " ");
}
RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
}
static ObjectClass MaskItem_class = {
.display = MaskItem_display,
.delete = MaskItem_delete
};
#ifdef HAVE_LIBHWLOC
static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bitmap_t cpuset, bool owner) {
MaskItem* this = AllocThis(MaskItem);
this->text = xStrdup(text);
this->indent = xStrdup(indent); /* nonnull for tree node */
this->value = 0;
this->ownCpuset = owner;
this->cpuset = cpuset;
this->sub_tree = hwloc_bitmap_weight(cpuset) > 1 ? 1 : 0;
this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
return this;
}
#endif
static MaskItem* MaskItem_newSingleton(const char* text, int cpu, bool isSet) {
MaskItem* this = AllocThis(MaskItem);
this->text = xStrdup(text);
this->indent = NULL; /* not a tree node */
this->sub_tree = 0;
this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
#ifdef HAVE_LIBHWLOC
this->ownCpuset = true;
this->cpuset = hwloc_bitmap_alloc();
hwloc_bitmap_set(this->cpuset, cpu);
(void)isSet;
#else
this->cpu = cpu;
#endif
this->value = 2 * isSet;
return this;
}
typedef struct AffinityPanel_ {
Panel super;
ProcessList* pl;
bool topoView;
Vector *cpuids;
unsigned width;
#ifdef HAVE_LIBHWLOC
MaskItem *topoRoot;
hwloc_const_cpuset_t allCpuset;
hwloc_bitmap_t workCpuset;
#endif
} AffinityPanel;
static void AffinityPanel_delete(Object* cast) {
AffinityPanel* this = (AffinityPanel*) cast;
Panel* super = (Panel*) this;
Panel_done(super);
Vector_delete(this->cpuids);
#ifdef HAVE_LIBHWLOC
hwloc_bitmap_free(this->workCpuset);
MaskItem_delete((Object*) this->topoRoot);
#endif
free(this);
}
#ifdef HAVE_LIBHWLOC
static void AffinityPanel_updateItem(AffinityPanel* this, MaskItem* item) {
Panel* super = (Panel*) this;
item->value = hwloc_bitmap_isincluded(item->cpuset, this->workCpuset) ? 2 :
hwloc_bitmap_intersects(item->cpuset, this->workCpuset) ? 1 : 0;
Panel_add(super, (Object*) item);
}
static void AffinityPanel_updateTopo(AffinityPanel* this, MaskItem* item) {
AffinityPanel_updateItem(this, item);
if (item->sub_tree == 2)
return;
for (int i = 0; i < Vector_size(item->children); i++)
AffinityPanel_updateTopo(this, (MaskItem*) Vector_get(item->children, i));
}
#endif
static void AffinityPanel_update(AffinityPanel* this, bool keepSelected) {
Panel* super = (Panel*) this;
FunctionBar_setLabel(super->currentBar, KEY_F(3), this->topoView ? "Collapse/Expand" : "");
FunctionBar_draw(super->currentBar, NULL);
int oldSelected = Panel_getSelectedIndex(super);
Panel_prune(super);
#ifdef HAVE_LIBHWLOC
if (this->topoView)
AffinityPanel_updateTopo(this, this->topoRoot);
else {
for (int i = 0; i < Vector_size(this->cpuids); i++)
AffinityPanel_updateItem(this, (MaskItem*) Vector_get(this->cpuids, i));
}
#else
Panel_splice(super, this->cpuids);
#endif
if (keepSelected)
Panel_setSelected(super, oldSelected);
super->needsRedraw = true;
}
static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) {
AffinityPanel* this = (AffinityPanel*) super;
HandlerResult result = IGNORED;
MaskItem* selected = (MaskItem*) Panel_getSelected(super);
bool keepSelected = true;
static HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) {
CheckItem* selected = (CheckItem*) Panel_getSelected(this);
switch(ch) { switch(ch) {
case KEY_MOUSE: case KEY_MOUSE:
case KEY_RECLICK: case KEY_RECLICK:
case ' ': case ' ':
#ifdef HAVE_LIBHWLOC CheckItem_set(selected, ! (CheckItem_get(selected)) );
if (selected->value == 2) { return HANDLED;
/* Item was selected, so remove this mask from the top cpuset. */
hwloc_bitmap_andnot(this->workCpuset, this->workCpuset, selected->cpuset);
selected->value = 0;
} else {
/* Item was not or only partial selected, so set all bits from this object
in the top cpuset. */
hwloc_bitmap_or(this->workCpuset, this->workCpuset, selected->cpuset);
selected->value = 2;
}
#else
selected->value = 2 * !selected->value; /* toggle between 0 and 2 */
#endif
result = HANDLED;
break;
#ifdef HAVE_LIBHWLOC
case KEY_F(1):
hwloc_bitmap_copy(this->workCpuset, this->allCpuset);
result = HANDLED;
break;
case KEY_F(2):
this->topoView = !this->topoView;
keepSelected = false;
result = HANDLED;
break;
case KEY_F(3):
case '-':
case '+':
if (selected->sub_tree)
selected->sub_tree = 1 + !(selected->sub_tree - 1); /* toggle between 1 and 2 */
result = HANDLED;
break;
#endif
case 0x0a: case 0x0a:
case 0x0d: case 0x0d:
case KEY_ENTER: case KEY_ENTER:
result = BREAK_LOOP; return BREAK_LOOP;
break;
} }
return IGNORED;
if (HANDLED == result)
AffinityPanel_update(this, keepSelected);
return result;
} }
#ifdef HAVE_LIBHWLOC
static MaskItem *AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem *parent) {
const char* type_name = hwloc_obj_type_string(obj->type);
const char* index_prefix = "#";
unsigned depth = obj->depth;
unsigned index = obj->logical_index;
size_t off = 0, left = 10 * depth;
char buf[64], indent_buf[left + 1];
if (obj->type == HWLOC_OBJ_PU) {
index = Settings_cpuId(this->pl->settings, obj->os_index);
type_name = "CPU";
index_prefix = "";
}
indent_buf[0] = '\0';
if (depth > 0) {
for (unsigned i = 1; i < depth; i++) {
xSnprintf(&indent_buf[off], left, "%s ", (indent & (1u << i)) ? CRT_treeStr[TREE_STR_VERT] : " ");
size_t len = strlen(&indent_buf[off]);
off += len, left -= len;
}
xSnprintf(&indent_buf[off], left, "%s",
obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND]);
size_t len = strlen(&indent_buf[off]);
off += len, left -= len;
}
xSnprintf(buf, 64, "%s %s%u", type_name, index_prefix, index);
MaskItem *item = MaskItem_newMask(buf, indent_buf, obj->complete_cpuset, false);
if (parent)
Vector_add(parent->children, item);
if (item->sub_tree && parent && parent->sub_tree == 1) {
/* if obj is fully included or fully excluded, collapse the item */
hwloc_bitmap_t result = hwloc_bitmap_alloc();
hwloc_bitmap_and(result, obj->complete_cpuset, this->workCpuset);
int weight = hwloc_bitmap_weight(result);
hwloc_bitmap_free(result);
if (weight == 0 || weight == (hwloc_bitmap_weight(this->workCpuset) + hwloc_bitmap_weight(obj->complete_cpuset)))
item->sub_tree = 2;
}
/* "[x] " + "|- " * depth + ("- ")?(if root node) + name */
unsigned width = 4 + 3 * depth + (2 * !depth) + strlen(buf);
if (width > this->width)
this->width = width;
return item;
}
static MaskItem *AffinityPanel_buildTopology(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem *parent) {
MaskItem *item = AffinityPanel_addObject(this, obj, indent, parent);
if (obj->next_sibling) {
indent |= (1u << obj->depth);
} else {
indent &= ~(1u << obj->depth);
}
for (unsigned i = 0; i < obj->arity; i++)
AffinityPanel_buildTopology(this, obj->children[i], indent, item);
return parent == NULL ? item : NULL;
}
#endif
PanelClass AffinityPanel_class = { PanelClass AffinityPanel_class = {
.super = { .super = {
.extends = Class(Panel), .extends = Class(Panel),
.delete = AffinityPanel_delete .delete = Panel_delete
}, },
.eventHandler = AffinityPanel_eventHandler .eventHandler = AffinityPanel_eventHandler
}; };
static const char* const AffinityPanelFunctions[] = { Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity) {
"Set ", Panel* this = Panel_new(1, 1, 1, 1, true, Class(CheckItem), FunctionBar_newEnterEsc("Set ", "Cancel "));
"Cancel ", Object_setClass(this, Class(AffinityPanel));
#ifdef HAVE_LIBHWLOC
"All",
"Topology",
" ",
#endif
NULL
};
static const char* const AffinityPanelKeys[] = {"Enter", "Esc", "F1", "F2", "F3"};
static const int AffinityPanelEvents[] = {13, 27, KEY_F(1), KEY_F(2), KEY_F(3)};
Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity, int* width) {
AffinityPanel* this = AllocThis(AffinityPanel);
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(MaskItem), false, FunctionBar_new(AffinityPanelFunctions, AffinityPanelKeys, AffinityPanelEvents));
this->pl = pl;
/* defaults to 15, this also includes the gap between the panels,
* but this will be added by the caller */
this->width = 14;
this->cpuids = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
#ifdef HAVE_LIBHWLOC
this->topoView = pl->settings->topologyAffinity;
#else
this->topoView = false;
#endif
#ifdef HAVE_LIBHWLOC
this->allCpuset = hwloc_topology_get_complete_cpuset(pl->topology);
this->workCpuset = hwloc_bitmap_alloc();
#endif
Panel_setHeader(super, "Use CPUs:");
Panel_setHeader(this, "Use CPUs:");
int curCpu = 0; int curCpu = 0;
for (int i = 0; i < pl->cpuCount; i++) { for (int i = 0; i < pl->cpuCount; i++) {
char number[16]; char number[10];
xSnprintf(number, 9, "CPU %d", Settings_cpuId(pl->settings, i)); xSnprintf(number, 9, "%d", Settings_cpuId(pl->settings, i));
unsigned cpu_width = 4 + strlen(number); bool mode;
if (cpu_width > this->width)
this->width = cpu_width;
bool isSet = false;
if (curCpu < affinity->used && affinity->cpus[curCpu] == i) { if (curCpu < affinity->used && affinity->cpus[curCpu] == i) {
#ifdef HAVE_LIBHWLOC mode = true;
hwloc_bitmap_set(this->workCpuset, i);
#endif
isSet = true;
curCpu++; curCpu++;
} else {
mode = false;
}
Panel_add(this, (Object*) CheckItem_newByVal(xStrdup(number), mode));
}
return this;
} }
MaskItem* cpuItem = MaskItem_newSingleton(number, i, isSet); Affinity* AffinityPanel_getAffinity(Panel* this, ProcessList* pl) {
Vector_add(this->cpuids, (Object*) cpuItem);
}
#ifdef HAVE_LIBHWLOC
this->topoRoot = AffinityPanel_buildTopology(this, hwloc_get_root_obj(pl->topology), 0, NULL);
#endif
if (width)
*width = this->width;
AffinityPanel_update(this, false);
return super;
}
Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) {
AffinityPanel* this = (AffinityPanel*) super;
Affinity* affinity = Affinity_new(pl); Affinity* affinity = Affinity_new(pl);
int size = Panel_size(this);
#ifdef HAVE_LIBHWLOC for (int i = 0; i < size; i++) {
int i; if (CheckItem_get((CheckItem*)Panel_get(this, i)))
hwloc_bitmap_foreach_begin(i, this->workCpuset)
Affinity_add(affinity, i); Affinity_add(affinity, i);
hwloc_bitmap_foreach_end();
#else
for (int i = 0; i < this->pl->cpuCount; i++) {
MaskItem* item = (MaskItem*)Vector_get(this->cpuids, i);
if (item->value)
Affinity_add(affinity, item->cpu);
} }
#endif
return affinity; return affinity;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AffinityPanel #ifndef HEADER_AffinityPanel
#define HEADER_AffinityPanel #define HEADER_AffinityPanel
/* /*
@ -10,11 +12,12 @@ in the source distribution for its full text.
#include "Panel.h" #include "Panel.h"
#include "Affinity.h" #include "Affinity.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "ListItem.h"
extern PanelClass AffinityPanel_class; extern PanelClass AffinityPanel_class;
Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity, int* width); Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity);
Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl); Affinity* AffinityPanel_getAffinity(Panel* this, ProcessList* pl);
#endif #endif

View File

@ -16,6 +16,15 @@ in the source distribution for its full text.
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
/*{
#include "Panel.h"
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
} AvailableColumnsPanel;
}*/
static const char* const AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL}; static const char* const AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL};

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableColumnsPanel #ifndef HEADER_AvailableColumnsPanel
#define HEADER_AvailableColumnsPanel #define HEADER_AvailableColumnsPanel
/* /*
@ -14,6 +16,7 @@ typedef struct AvailableColumnsPanel_ {
Panel* columns; Panel* columns;
} AvailableColumnsPanel; } AvailableColumnsPanel;
extern PanelClass AvailableColumnsPanel_class; extern PanelClass AvailableColumnsPanel_class;
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns); AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns);

View File

@ -16,6 +16,23 @@ in the source distribution for its full text.
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Settings.h"
#include "Panel.h"
#include "ScreenManager.h"
#include "ProcessList.h"
typedef struct AvailableMetersPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
Header* header;
Panel* leftPanel;
Panel* rightPanel;
} AvailableMetersPanel;
}*/
static void AvailableMetersPanel_delete(Object* object) { static void AvailableMetersPanel_delete(Object* object) {
Panel* super = (Panel*) object; Panel* super = (Panel*) object;
@ -110,7 +127,7 @@ AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* heade
Panel_add(super, (Object*) ListItem_new("CPU average", 0)); Panel_add(super, (Object*) ListItem_new("CPU average", 0));
for (int i = 1; i <= cpus; i++) { for (int i = 1; i <= cpus; i++) {
char buffer[50]; char buffer[50];
xSnprintf(buffer, 50, "%s %d", type->uiName, Settings_cpuId(this->settings, i - 1)); xSnprintf(buffer, 50, "%s %d", type->uiName, i);
Panel_add(super, (Object*) ListItem_new(buffer, i)); Panel_add(super, (Object*) ListItem_new(buffer, i));
} }
} else { } else {

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableMetersPanel #ifndef HEADER_AvailableMetersPanel
#define HEADER_AvailableMetersPanel #define HEADER_AvailableMetersPanel
/* /*
@ -22,6 +24,7 @@ typedef struct AvailableMetersPanel_ {
Panel* rightPanel; Panel* rightPanel;
} AvailableMetersPanel; } AvailableMetersPanel;
extern PanelClass AvailableMetersPanel_class; extern PanelClass AvailableMetersPanel_class;
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, ProcessList* pl); AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, ProcessList* pl);

View File

@ -18,6 +18,15 @@ This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Meter.h"
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
}*/
int BatteryMeter_attributes[] = { int BatteryMeter_attributes[] = {
BATTERY BATTERY

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_BatteryMeter #ifndef HEADER_BatteryMeter
#define HEADER_BatteryMeter #define HEADER_BatteryMeter
/* /*

View File

@ -1,34 +1,56 @@
Contributing Guide Contributing Guide
================== ==================
Thank you so much for taking the time to contribute in to htop! Hello, and thank you so much for taking your time to contribute in any way to
htop! There are many ways to contribute, and I'll try to list them below. The
support from the free software community has been amazing over the years and
it is the number one thing that keeps me going, maintaining and improving
something that started as a tiny pet project back in 2004 and that nowadays is
a piece of software used all over the world, in both reality [and
fiction!](http://hisham.hm/htop/index.php?page=sightings). Cheers!
-- Hisham Muhammad
Bug Reports Bug Reports
----------- -----------
Bug reports should be posted in the [Github issue Bug reports should be posted in the [Github issue
tracker](https://github.com/htop-dev/htop/issues). tracker](http://github.com/hishamhm/htop/issues). (I reply to them all, but I
Bug reports are extremely important since it's impossible for us to test usually do it in batches! :) ) Bug reports are extremely important since it's
htop in every possible system, distribution and scenario. Your feedback impossible for me to test htop in every possible system, distribution and
is what keeps the tool stable and always improving! Thank you! scenario. Your feedback is what keeps the tool stable and always improving!
Thank you!
Pull Requests Pull Requests
------------- -------------
Code contributions are most welcome! Just [fork the Code contributions are most welcome! Just [fork the
repo](https://github.com/htop-dev/htop) and send a [pull repo](http://github.com/hishamhm/htop) and send a [pull
request](https://github.com/htop-dev/htop/pulls). Help is especially request](https://github.com/hishamhm/htop/pulls). Help is especially
appreciated for support of platforms other than Linux. If proposing new appreciated for support of platforms other than Linux. If proposing new
features, please be mindful that htop is a system tool that needs to keep a features, please be mindful that htop is a system tool that needs to keep a
small footprint and perform well on systems under stress -- so unfortunately small footprint and perform well on systems under stress -- so unfortunately I
we can't accept every new feature proposed, as we need to keep the tool slim can't accept every new feature proposed, as I need to keep the tool slim and
and maintainable. Great ideas backed by a PR are always carefully considered maintainable. Great ideas backed by a PR are always carefully considered for
for inclusion though! Also, PRs containing bug fixes and portability tweaks inclusion, though! Also, PRs containing bug fixes and portability tweaks are a
are always included, please send those in! no-brainer, please send those in!
Feature Requests Feature Requests
---------------- ----------------
Please label Github issues that are feature requests with the [`feature Back when htop was hosted in SourceForge, there used to be separate Bug
request`](https://github.com/htop-dev/htop/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22feature+request%22+) Tracker and Feature Request pages. These go all lumped together under "Issues"
label. in Github, which is a bit confusing. For this reason, I close Feature Requests
and file them with the [`feature
request`](https://github.com/hishamhm/htop/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22feature+request%22+)
label, where they remain accessible, but not mixed with actual bug reports.
This doesn't mean I'm dismissing or ignoring feature requests right away! It's
just an organizational issue (with Github, really!).
Donations
---------
If you like htop, feel free to [buy the author a
beer](http://hisham.hm/htop/index.php?page=donate). :-)

View File

@ -353,3 +353,4 @@ Public License instead of this License.
applicable licenses of the version of PLPA used in your combined work, applicable licenses of the version of PLPA used in your combined work,
provided that you include the source code of such version of PLPA when provided that you include the source code of such version of PLPA when
and as the GNU GPL requires distribution of source code. and as the GNU GPL requires distribution of source code.

View File

@ -16,10 +16,34 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
/*{
#include "Meter.h"
typedef enum {
CPU_METER_NICE = 0,
CPU_METER_NORMAL = 1,
CPU_METER_KERNEL = 2,
CPU_METER_IRQ = 3,
CPU_METER_SOFTIRQ = 4,
CPU_METER_STEAL = 5,
CPU_METER_GUEST = 6,
CPU_METER_IOWAIT = 7,
CPU_METER_ITEMCOUNT = 8, // number of entries in this enum
} CPUMeterValues;
}*/
int CPUMeter_attributes[] = { int CPUMeter_attributes[] = {
CPU_NICE, CPU_NORMAL, CPU_SYSTEM, CPU_IRQ, CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, CPU_IOWAIT CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, 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) { static void CPUMeter_init(Meter* this) {
int cpu = this->param; int cpu = this->param;
if (this->pl->cpuCount > 1) { if (this->pl->cpuCount > 1) {
@ -39,24 +63,7 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, int size) {
} }
memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT); memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT);
double percent = Platform_setCPUValues(this, cpu); double percent = Platform_setCPUValues(this, cpu);
if (this->pl->settings->showCPUFrequency) {
double cpuFrequency = this->values[CPU_METER_FREQUENCY];
char cpuFrequencyBuffer[16];
if (cpuFrequency < 0) {
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
} else {
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%.0fMHz", cpuFrequency);
}
if (this->pl->settings->showCPUUsage) {
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
} else {
xSnprintf(buffer, size, "%s", cpuFrequencyBuffer);
}
} else if (this->pl->settings->showCPUUsage) {
xSnprintf(buffer, size, "%5.1f%%", percent); xSnprintf(buffer, size, "%5.1f%%", percent);
} else if (size > 0) {
buffer[0] = '\0';
}
} }
static void CPUMeter_display(Object* cast, RichString* out) { static void CPUMeter_display(Object* cast, RichString* out) {
@ -73,7 +80,7 @@ static void CPUMeter_display(Object* cast, RichString* out) {
if (this->pl->settings->detailedCPUTime) { if (this->pl->settings->detailedCPUTime) {
xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
RichString_append(out, CRT_colors[METER_TEXT], "sy:"); RichString_append(out, CRT_colors[METER_TEXT], "sy:");
RichString_append(out, CRT_colors[CPU_SYSTEM], buffer); RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
RichString_append(out, CRT_colors[METER_TEXT], "ni:"); RichString_append(out, CRT_colors[METER_TEXT], "ni:");
RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer); RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer);
@ -99,7 +106,7 @@ static void CPUMeter_display(Object* cast, RichString* out) {
} else { } else {
xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
RichString_append(out, CRT_colors[METER_TEXT], "sys:"); RichString_append(out, CRT_colors[METER_TEXT], "sys:");
RichString_append(out, CRT_colors[CPU_SYSTEM], buffer); RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
RichString_append(out, CRT_colors[METER_TEXT], "low:"); RichString_append(out, CRT_colors[METER_TEXT], "low:");
RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer); RichString_append(out, CRT_colors[CPU_NICE_TEXT], buffer);
@ -130,15 +137,6 @@ static void AllCPUsMeter_getRange(Meter* this, int* start, int* count) {
} }
} }
static int MapClassnameToColumncount(Meter* this){
if (strchr(Meter_name(this), '4'))
return 4;
else if (strchr(Meter_name(this), '2'))
return 2;
else
return 1;
}
static void AllCPUsMeter_init(Meter* this) { static void AllCPUsMeter_init(Meter* this) {
int cpus = this->pl->cpuCount; int cpus = this->pl->cpuCount;
if (!this->drawData) if (!this->drawData)
@ -154,8 +152,10 @@ static void AllCPUsMeter_init(Meter* this) {
if (this->mode == 0) if (this->mode == 0)
this->mode = BAR_METERMODE; this->mode = BAR_METERMODE;
int h = Meter_modes[this->mode]->h; int h = Meter_modes[this->mode]->h;
int ncol = MapClassnameToColumncount(this); if (strchr(Meter_name(this), '2'))
this->h = h * ((count + ncol - 1)/ ncol); this->h = h * ((count+1) / 2);
else
this->h = h * count;
} }
static void AllCPUsMeter_done(Meter* this) { static void AllCPUsMeter_done(Meter* this) {
@ -175,8 +175,10 @@ static void AllCPUsMeter_updateMode(Meter* this, int mode) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Meter_setMode(meters[i], mode); Meter_setMode(meters[i], mode);
} }
int ncol = MapClassnameToColumncount(this); if (strchr(Meter_name(this), '2'))
this->h = h * ((count + ncol - 1)/ ncol); this->h = h * ((count+1) / 2);
else
this->h = h * count;
} }
static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) { static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) {
@ -207,22 +209,6 @@ static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) {
} }
} }
static void MultiColCPUsMeter_draw(Meter* this, int x, int y, int w){
Meter** meters = (Meter**) this->drawData;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
int ncol = MapClassnameToColumncount(this);
int colwidth = (w-ncol)/ncol + 1;
int diff = (w - (colwidth * ncol));
int nrows = (count + ncol - 1) / ncol;
for (int i = 0; i < count; i++){
int d = (i/nrows) > diff ? diff : (i / nrows) ; // dynamic spacer
int xpos = x + ((i / nrows) * colwidth) + d;
int ypos = y + ((i % nrows) * meters[0]->h);
meters[i]->draw(meters[i], xpos, ypos, colwidth);
}
}
MeterClass CPUMeter_class = { MeterClass CPUMeter_class = {
.super = { .super = {
.extends = Class(Meter), .extends = Class(Meter),
@ -354,59 +340,3 @@ MeterClass RightCPUs2Meter_class = {
.done = AllCPUsMeter_done .done = AllCPUsMeter_done
}; };
MeterClass AllCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs4",
.uiName = "CPUs (1&2&3&4/4)",
.description = "CPUs (1&2&3&4/4): all CPUs in 4 shorter columns",
.caption = "CPU",
.draw = MultiColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass LeftCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs4",
.uiName = "CPUs (1-4/8)",
.description = "CPUs (1-4/8): first half in 4 shorter columns",
.caption = "CPU",
.draw = MultiColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
MeterClass RightCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs4",
.uiName = "CPUs (5-8/8)",
.description = "CPUs (5-8/8): second half in 4 shorter columns",
.caption = "CPU",
.draw = MultiColCPUsMeter_draw,
.init = AllCPUsMeter_init,
.updateMode = AllCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CPUMeter #ifndef HEADER_CPUMeter
#define HEADER_CPUMeter #define HEADER_CPUMeter
/* /*
@ -18,12 +20,19 @@ typedef enum {
CPU_METER_STEAL = 5, CPU_METER_STEAL = 5,
CPU_METER_GUEST = 6, CPU_METER_GUEST = 6,
CPU_METER_IOWAIT = 7, CPU_METER_IOWAIT = 7,
CPU_METER_FREQUENCY = 8, CPU_METER_ITEMCOUNT = 8, // number of entries in this enum
CPU_METER_ITEMCOUNT = 9, // number of entries in this enum
} CPUMeterValues; } CPUMeterValues;
extern int CPUMeter_attributes[]; extern int CPUMeter_attributes[];
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
extern MeterClass CPUMeter_class; extern MeterClass CPUMeter_class;
extern MeterClass AllCPUsMeter_class; extern MeterClass AllCPUsMeter_class;
@ -38,10 +47,5 @@ extern MeterClass LeftCPUs2Meter_class;
extern MeterClass RightCPUs2Meter_class; extern MeterClass RightCPUs2Meter_class;
extern MeterClass AllCPUs4Meter_class;
extern MeterClass LeftCPUs4Meter_class;
extern MeterClass RightCPUs4Meter_class;
#endif #endif

233
CRT.c
View File

@ -39,6 +39,112 @@ in the source distribution for its full text.
#define ColorPairGrayBlack ColorPair(Magenta,Magenta) #define ColorPairGrayBlack ColorPair(Magenta,Magenta)
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta) #define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
#define KEY_WHEELUP KEY_F(20)
#define KEY_WHEELDOWN KEY_F(21)
#define KEY_RECLICK KEY_F(22)
#define KEY_SHIFT_TAB KEY_F(23)
//#link curses
/*{
#include <stdbool.h>
typedef enum TreeStr_ {
TREE_STR_HORZ,
TREE_STR_VERT,
TREE_STR_RTEE,
TREE_STR_BEND,
TREE_STR_TEND,
TREE_STR_OPEN,
TREE_STR_SHUT,
TREE_STR_COUNT
} TreeStr;
typedef enum ColorSchemes_ {
COLORSCHEME_DEFAULT = 0,
COLORSCHEME_MONOCHROME = 1,
COLORSCHEME_BLACKONWHITE = 2,
COLORSCHEME_LIGHTTERMINAL = 3,
COLORSCHEME_MIDNIGHT = 4,
COLORSCHEME_BLACKNIGHT = 5,
COLORSCHEME_BROKENGRAY = 6,
LAST_COLORSCHEME = 7,
} ColorSchemes;
typedef enum ColorElements_ {
RESET_COLOR,
DEFAULT_COLOR,
FUNCTION_BAR,
FUNCTION_KEY,
FAILED_SEARCH,
PANEL_HEADER_FOCUS,
PANEL_HEADER_UNFOCUS,
PANEL_SELECTION_FOCUS,
PANEL_SELECTION_FOLLOW,
PANEL_SELECTION_UNFOCUS,
LARGE_NUMBER,
METER_TEXT,
METER_VALUE,
LED_COLOR,
UPTIME,
BATTERY,
TASKS_RUNNING,
SWAP,
PROCESS,
PROCESS_SHADOW,
PROCESS_TAG,
PROCESS_MEGABYTES,
PROCESS_TREE,
PROCESS_R_STATE,
PROCESS_D_STATE,
PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY,
PROCESS_THREAD,
PROCESS_THREAD_BASENAME,
BAR_BORDER,
BAR_SHADOW,
GRAPH_1,
GRAPH_2,
MEMORY_USED,
MEMORY_BUFFERS,
MEMORY_BUFFERS_TEXT,
MEMORY_CACHE,
LOAD,
LOAD_AVERAGE_FIFTEEN,
LOAD_AVERAGE_FIVE,
LOAD_AVERAGE_ONE,
CHECK_BOX,
CHECK_MARK,
CHECK_TEXT,
CLOCK,
HELP_BOLD,
HOSTNAME,
CPU_NICE,
CPU_NICE_TEXT,
CPU_NORMAL,
CPU_KERNEL,
CPU_IOWAIT,
CPU_IRQ,
CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
PANEL_EDIT,
SCREENS_OTH_BORDER,
SCREENS_OTH_TEXT,
SCREENS_CUR_BORDER,
SCREENS_CUR_TEXT,
LAST_COLORELEMENT
} ColorElements;
void CRT_fatalError(const char* note) __attribute__ ((noreturn));
void CRT_handleSIGSEGV(int sgn);
#define KEY_ALT(x) (KEY_F(64 - 26) + (x - 'A'))
}*/
const char *CRT_treeStrAscii[TREE_STR_COUNT] = { const char *CRT_treeStrAscii[TREE_STR_COUNT] = {
"-", // TREE_STR_HORZ "-", // TREE_STR_HORZ
"|", // TREE_STR_VERT "|", // TREE_STR_VERT
@ -57,9 +163,7 @@ const char *CRT_treeStrUtf8[TREE_STR_COUNT] = {
"\xe2\x94\x9c", // TREE_STR_RTEE ├ "\xe2\x94\x9c", // TREE_STR_RTEE ├
"\xe2\x94\x94", // TREE_STR_BEND └ "\xe2\x94\x94", // TREE_STR_BEND └
"\xe2\x94\x8c", // TREE_STR_TEND ┌ "\xe2\x94\x8c", // TREE_STR_TEND ┌
"+", // TREE_STR_OPEN +, TODO use 🮯 'BOX DRAWINGS LIGHT HORIZONTAL "+", // TREE_STR_OPEN +
// WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
// Unicode 13 is common
"\xe2\x94\x80", // TREE_STR_SHUT ─ "\xe2\x94\x80", // TREE_STR_SHUT ─
}; };
@ -128,22 +232,17 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = ColorPair(Blue,Black), [CPU_NICE] = ColorPair(Blue,Black),
[CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black), [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black),
[CPU_NORMAL] = ColorPair(Green,Black), [CPU_NORMAL] = ColorPair(Green,Black),
[CPU_SYSTEM] = ColorPair(Red,Black), [CPU_KERNEL] = ColorPair(Red,Black),
[CPU_IOWAIT] = A_BOLD | ColorPairGrayBlack, [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black),
[CPU_IRQ] = ColorPair(Yellow,Black), [CPU_IRQ] = ColorPair(Yellow,Black),
[CPU_SOFTIRQ] = ColorPair(Magenta,Black), [CPU_SOFTIRQ] = ColorPair(Magenta,Black),
[CPU_STEAL] = ColorPair(Cyan,Black), [CPU_STEAL] = ColorPair(Cyan,Black),
[CPU_GUEST] = ColorPair(Cyan,Black), [CPU_GUEST] = ColorPair(Cyan,Black),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan,Black), [PANEL_EDIT] = ColorPair(White,Blue),
[PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan,Black), [SCREENS_OTH_BORDER] = ColorPair(Blue,Blue),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White,Black), [SCREENS_OTH_TEXT] = ColorPair(Black,Blue),
[ZFS_MFU] = ColorPair(Blue,Black), [SCREENS_CUR_BORDER] = ColorPair(Green,Green),
[ZFS_MRU] = ColorPair(Yellow,Black), [SCREENS_CUR_TEXT] = ColorPair(Black,Green),
[ZFS_ANON] = ColorPair(Magenta,Black),
[ZFS_HEADER] = ColorPair(Cyan,Black),
[ZFS_OTHER] = ColorPair(Magenta,Black),
[ZFS_COMPRESSED] = ColorPair(Blue,Black),
[ZFS_RATIO] = ColorPair(Magenta,Black),
}, },
[COLORSCHEME_MONOCHROME] = { [COLORSCHEME_MONOCHROME] = {
[RESET_COLOR] = A_NORMAL, [RESET_COLOR] = A_NORMAL,
@ -197,22 +296,17 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = A_NORMAL, [CPU_NICE] = A_NORMAL,
[CPU_NICE_TEXT] = A_NORMAL, [CPU_NICE_TEXT] = A_NORMAL,
[CPU_NORMAL] = A_BOLD, [CPU_NORMAL] = A_BOLD,
[CPU_SYSTEM] = A_BOLD, [CPU_KERNEL] = A_BOLD,
[CPU_IOWAIT] = A_NORMAL, [CPU_IOWAIT] = A_NORMAL,
[CPU_IRQ] = A_BOLD, [CPU_IRQ] = A_BOLD,
[CPU_SOFTIRQ] = A_BOLD, [CPU_SOFTIRQ] = A_BOLD,
[CPU_STEAL] = A_REVERSE, [CPU_STEAL] = A_REVERSE,
[CPU_GUEST] = A_REVERSE, [CPU_GUEST] = A_REVERSE,
[PRESSURE_STALL_THREEHUNDRED] = A_DIM, [PANEL_EDIT] = A_BOLD,
[PRESSURE_STALL_SIXTY] = A_NORMAL, [SCREENS_OTH_BORDER] = A_DIM,
[PRESSURE_STALL_TEN] = A_BOLD, [SCREENS_OTH_TEXT] = A_DIM,
[ZFS_MFU] = A_NORMAL, [SCREENS_CUR_BORDER] = A_REVERSE,
[ZFS_MRU] = A_NORMAL, [SCREENS_CUR_TEXT] = A_REVERSE,
[ZFS_ANON] = A_DIM,
[ZFS_HEADER] = A_BOLD,
[ZFS_OTHER] = A_DIM,
[ZFS_COMPRESSED] = A_BOLD,
[ZFS_RATIO] = A_BOLD,
}, },
[COLORSCHEME_BLACKONWHITE] = { [COLORSCHEME_BLACKONWHITE] = {
[RESET_COLOR] = ColorPair(Black,White), [RESET_COLOR] = ColorPair(Black,White),
@ -266,22 +360,17 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = ColorPair(Cyan,White), [CPU_NICE] = ColorPair(Cyan,White),
[CPU_NICE_TEXT] = ColorPair(Cyan,White), [CPU_NICE_TEXT] = ColorPair(Cyan,White),
[CPU_NORMAL] = ColorPair(Green,White), [CPU_NORMAL] = ColorPair(Green,White),
[CPU_SYSTEM] = ColorPair(Red,White), [CPU_KERNEL] = ColorPair(Red,White),
[CPU_IOWAIT] = A_BOLD | ColorPair(Black, White), [CPU_IOWAIT] = A_BOLD | ColorPair(Black, White),
[CPU_IRQ] = ColorPair(Blue,White), [CPU_IRQ] = ColorPair(Blue,White),
[CPU_SOFTIRQ] = ColorPair(Blue,White), [CPU_SOFTIRQ] = ColorPair(Blue,White),
[CPU_STEAL] = ColorPair(Cyan,White), [CPU_STEAL] = ColorPair(Cyan,White),
[CPU_GUEST] = ColorPair(Cyan,White), [CPU_GUEST] = ColorPair(Cyan,White),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black,White), [PANEL_EDIT] = ColorPair(White,Blue),
[PRESSURE_STALL_SIXTY] = ColorPair(Black,White), [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Black,White),
[PRESSURE_STALL_TEN] = ColorPair(Black,White), [SCREENS_OTH_TEXT] = A_BOLD | ColorPair(Black,White),
[ZFS_MFU] = ColorPair(Cyan,White), [SCREENS_CUR_BORDER] = ColorPair(Green,Green),
[ZFS_MRU] = ColorPair(Yellow,White), [SCREENS_CUR_TEXT] = ColorPair(Black,Green),
[ZFS_ANON] = ColorPair(Magenta,White),
[ZFS_HEADER] = ColorPair(Yellow,White),
[ZFS_OTHER] = ColorPair(Magenta,White),
[ZFS_COMPRESSED] = ColorPair(Cyan,White),
[ZFS_RATIO] = ColorPair(Magenta,White),
}, },
[COLORSCHEME_LIGHTTERMINAL] = { [COLORSCHEME_LIGHTTERMINAL] = {
[RESET_COLOR] = ColorPair(Black,Black), [RESET_COLOR] = ColorPair(Black,Black),
@ -335,22 +424,17 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = ColorPair(Cyan,Black), [CPU_NICE] = ColorPair(Cyan,Black),
[CPU_NICE_TEXT] = ColorPair(Cyan,Black), [CPU_NICE_TEXT] = ColorPair(Cyan,Black),
[CPU_NORMAL] = ColorPair(Green,Black), [CPU_NORMAL] = ColorPair(Green,Black),
[CPU_SYSTEM] = ColorPair(Red,Black), [CPU_KERNEL] = ColorPair(Red,Black),
[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black), [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black),
[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black), [CPU_IRQ] = A_BOLD | ColorPair(Blue,Black),
[CPU_SOFTIRQ] = ColorPair(Blue,Black), [CPU_SOFTIRQ] = ColorPair(Blue,Black),
[CPU_STEAL] = ColorPair(Black,Black), [CPU_STEAL] = ColorPair(Black,Black),
[CPU_GUEST] = ColorPair(Black,Black), [CPU_GUEST] = ColorPair(Black,Black),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black,Black), [PANEL_EDIT] = ColorPair(White,Blue),
[PRESSURE_STALL_SIXTY] = ColorPair(Black,Black), [SCREENS_OTH_BORDER] = ColorPair(Blue,Black),
[PRESSURE_STALL_TEN] = ColorPair(Black,Black), [SCREENS_OTH_TEXT] = ColorPair(Blue,Black),
[ZFS_MFU] = ColorPair(Cyan,Black), [SCREENS_CUR_BORDER] = ColorPair(Green,Green),
[ZFS_MRU] = ColorPair(Yellow,Black), [SCREENS_CUR_TEXT] = ColorPair(Black,Green),
[ZFS_ANON] = A_BOLD | ColorPair(Magenta,Black),
[ZFS_HEADER] = ColorPair(Black,Black),
[ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Black),
[ZFS_COMPRESSED] = ColorPair(Cyan,Black),
[ZFS_RATIO] = A_BOLD | ColorPair(Magenta,Black),
}, },
[COLORSCHEME_MIDNIGHT] = { [COLORSCHEME_MIDNIGHT] = {
[RESET_COLOR] = ColorPair(White,Blue), [RESET_COLOR] = ColorPair(White,Blue),
@ -404,22 +488,17 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue), [CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue),
[CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan,Blue), [CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan,Blue),
[CPU_NORMAL] = A_BOLD | ColorPair(Green,Blue), [CPU_NORMAL] = A_BOLD | ColorPair(Green,Blue),
[CPU_SYSTEM] = A_BOLD | ColorPair(Red,Blue), [CPU_KERNEL] = A_BOLD | ColorPair(Red,Blue),
[CPU_IOWAIT] = A_BOLD | ColorPair(Blue,Blue), [CPU_IOWAIT] = A_BOLD | ColorPair(Blue,Blue),
[CPU_IRQ] = A_BOLD | ColorPair(Black,Blue), [CPU_IRQ] = A_BOLD | ColorPair(Black,Blue),
[CPU_SOFTIRQ] = ColorPair(Black,Blue), [CPU_SOFTIRQ] = ColorPair(Black,Blue),
[CPU_STEAL] = ColorPair(White,Blue), [CPU_STEAL] = ColorPair(White,Blue),
[CPU_GUEST] = ColorPair(White,Blue), [CPU_GUEST] = ColorPair(White,Blue),
[PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black,Blue), [PANEL_EDIT] = ColorPair(White,Blue),
[PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White,Blue), [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Yellow,Blue),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White,Blue), [SCREENS_OTH_TEXT] = ColorPair(Cyan,Blue),
[ZFS_MFU] = A_BOLD | ColorPair(White,Blue), [SCREENS_CUR_BORDER] = ColorPair(Cyan,Cyan),
[ZFS_MRU] = A_BOLD | ColorPair(Yellow,Blue), [SCREENS_CUR_TEXT] = ColorPair(Black,Cyan),
[ZFS_ANON] = A_BOLD | ColorPair(Magenta,Blue),
[ZFS_HEADER] = A_BOLD | ColorPair(Yellow,Blue),
[ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Blue),
[ZFS_COMPRESSED] = A_BOLD | ColorPair(White,Blue),
[ZFS_RATIO] = A_BOLD | ColorPair(Magenta,Blue),
}, },
[COLORSCHEME_BLACKNIGHT] = { [COLORSCHEME_BLACKNIGHT] = {
[RESET_COLOR] = ColorPair(Cyan,Black), [RESET_COLOR] = ColorPair(Cyan,Black),
@ -473,28 +552,21 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_NICE] = ColorPair(Blue,Black), [CPU_NICE] = ColorPair(Blue,Black),
[CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black), [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue,Black),
[CPU_NORMAL] = ColorPair(Green,Black), [CPU_NORMAL] = ColorPair(Green,Black),
[CPU_SYSTEM] = ColorPair(Red,Black), [CPU_KERNEL] = ColorPair(Red,Black),
[CPU_IOWAIT] = ColorPair(Yellow,Black), [CPU_IOWAIT] = ColorPair(Yellow,Black),
[CPU_IRQ] = A_BOLD | ColorPair(Blue,Black), [CPU_IRQ] = A_BOLD | ColorPair(Blue,Black),
[CPU_SOFTIRQ] = ColorPair(Blue,Black), [CPU_SOFTIRQ] = ColorPair(Blue,Black),
[CPU_STEAL] = ColorPair(Cyan,Black), [CPU_STEAL] = ColorPair(Cyan,Black),
[CPU_GUEST] = ColorPair(Cyan,Black), [CPU_GUEST] = ColorPair(Cyan,Black),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green,Black), [PANEL_EDIT] = ColorPair(White,Cyan),
[PRESSURE_STALL_SIXTY] = ColorPair(Green,Black), [SCREENS_OTH_BORDER] = ColorPair(White,Black),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green,Black), [SCREENS_OTH_TEXT] = ColorPair(Cyan,Black),
[ZFS_MFU] = ColorPair(Blue,Black), [SCREENS_CUR_BORDER] = A_BOLD | ColorPair(White,Black),
[ZFS_MRU] = ColorPair(Yellow,Black), [SCREENS_CUR_TEXT] = A_BOLD | ColorPair(Green,Black),
[ZFS_ANON] = ColorPair(Magenta,Black),
[ZFS_HEADER] = ColorPair(Yellow,Black),
[ZFS_OTHER] = ColorPair(Magenta,Black),
[ZFS_COMPRESSED] = ColorPair(Blue,Black),
[ZFS_RATIO] = ColorPair(Magenta,Black),
}, },
[COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated.
}; };
int CRT_cursorX = 0;
int CRT_scrollHAmount = 5; int CRT_scrollHAmount = 5;
int CRT_scrollWheelVAmount = 10; int CRT_scrollWheelVAmount = 10;
@ -546,13 +618,18 @@ void CRT_restorePrivileges() {
#else #else
// In this case, the setuid operations are defined as macros in CRT.h /* Turn setuid operations into NOPs */
#ifndef CRT_dropPrivileges
#define CRT_dropPrivileges()
#define CRT_restorePrivileges()
#endif
#endif #endif
// TODO: pass an instance of Settings instead. // TODO: pass an instance of Settings instead.
void CRT_init(int delay, int colorScheme, bool allowUnicode) { void CRT_init(int delay, int colorScheme) {
initscr(); initscr();
noecho(); noecho();
CRT_delay = delay; CRT_delay = delay;
@ -598,12 +675,16 @@ void CRT_init(int delay, int colorScheme, bool allowUnicode) {
define_key("\033[13~", KEY_F(3)); define_key("\033[13~", KEY_F(3));
define_key("\033[14~", KEY_F(4)); define_key("\033[14~", KEY_F(4));
define_key("\033[17;2~", KEY_F(18)); define_key("\033[17;2~", KEY_F(18));
define_key("\033[Z", KEY_SHIFT_TAB);
char sequence[3] = "\033a"; char sequence[3] = "\033a";
for (char c = 'a'; c <= 'z'; c++) { for (char c = 'a'; c <= 'z'; c++) {
sequence[1] = c; sequence[1] = c;
define_key(sequence, KEY_ALT('A' + (c - 'a'))); define_key(sequence, KEY_ALT('A' + (c - 'a')));
} }
} }
if (String_startsWith(CRT_termType, "rxvt")) {
define_key("\033[Z", KEY_SHIFT_TAB);
}
#ifndef DEBUG #ifndef DEBUG
signal(11, CRT_handleSIGSEGV); signal(11, CRT_handleSIGSEGV);
#endif #endif
@ -618,12 +699,10 @@ void CRT_init(int delay, int colorScheme, bool allowUnicode) {
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
if (allowUnicode && strcmp(nl_langinfo(CODESET), "UTF-8") == 0) if(strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
CRT_utf8 = true; CRT_utf8 = true;
else else
CRT_utf8 = false; CRT_utf8 = false;
#else
(void) allowUnicode;
#endif #endif
CRT_treeStr = CRT_treeStr =

59
CRT.h
View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CRT #ifndef HEADER_CRT
#define HEADER_CRT #define HEADER_CRT
/* /*
@ -7,11 +9,33 @@ 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 <stdbool.h> #if HAVE_SETUID_ENABLED
#endif
#define ColorIndex(i,j) ((7-i)*8+j)
#define ColorPair(i,j) COLOR_PAIR(ColorIndex(i,j))
#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
#define ColorPairGrayBlack ColorPair(Magenta,Magenta)
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
#define KEY_WHEELUP KEY_F(20) #define KEY_WHEELUP KEY_F(20)
#define KEY_WHEELDOWN KEY_F(21) #define KEY_WHEELDOWN KEY_F(21)
#define KEY_RECLICK KEY_F(22) #define KEY_RECLICK KEY_F(22)
#define KEY_SHIFT_TAB KEY_F(23)
//#link curses
#include <stdbool.h>
typedef enum TreeStr_ { typedef enum TreeStr_ {
TREE_STR_HORZ, TREE_STR_HORZ,
@ -87,22 +111,17 @@ typedef enum ColorElements_ {
CPU_NICE, CPU_NICE,
CPU_NICE_TEXT, CPU_NICE_TEXT,
CPU_NORMAL, CPU_NORMAL,
CPU_SYSTEM, CPU_KERNEL,
CPU_IOWAIT, CPU_IOWAIT,
CPU_IRQ, CPU_IRQ,
CPU_SOFTIRQ, CPU_SOFTIRQ,
CPU_STEAL, CPU_STEAL,
CPU_GUEST, CPU_GUEST,
PRESSURE_STALL_TEN, PANEL_EDIT,
PRESSURE_STALL_SIXTY, SCREENS_OTH_BORDER,
PRESSURE_STALL_THREEHUNDRED, SCREENS_OTH_TEXT,
ZFS_MFU, SCREENS_CUR_BORDER,
ZFS_MRU, SCREENS_CUR_TEXT,
ZFS_ANON,
ZFS_HEADER,
ZFS_OTHER,
ZFS_COMPRESSED,
ZFS_RATIO,
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
@ -127,24 +146,26 @@ extern const char **CRT_treeStr;
extern int CRT_delay; extern int CRT_delay;
extern int* CRT_colors; int* CRT_colors;
extern int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT]; extern int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT];
extern int CRT_cursorX;
extern int CRT_scrollHAmount; extern int CRT_scrollHAmount;
extern int CRT_scrollWheelVAmount; extern int CRT_scrollWheelVAmount;
extern char* CRT_termType; char* CRT_termType;
// TODO move color scheme to Settings, perhaps?
extern int CRT_colorScheme; extern int CRT_colorScheme;
extern void *backtraceArray[128]; void *backtraceArray[128];
#if HAVE_SETUID_ENABLED #if HAVE_SETUID_ENABLED
#define DIE(msg) do { CRT_done(); fprintf(stderr, msg); exit(1); } while(0)
void CRT_dropPrivileges(); void CRT_dropPrivileges();
void CRT_restorePrivileges(); void CRT_restorePrivileges();
@ -160,7 +181,9 @@ void CRT_restorePrivileges();
#endif #endif
void CRT_init(int delay, int colorScheme, bool allowUnicode); // TODO: pass an instance of Settings instead.
void CRT_init(int delay, int colorScheme);
void CRT_done(); void CRT_done();

View File

@ -10,13 +10,29 @@ in the source distribution for its full text.
#include "AvailableMetersPanel.h" #include "AvailableMetersPanel.h"
#include "MetersPanel.h" #include "MetersPanel.h"
#include "DisplayOptionsPanel.h" #include "DisplayOptionsPanel.h"
#include "ColumnsPanel.h" #include "ScreensPanel.h"
#include "ColorsPanel.h" #include "ColorsPanel.h"
#include "AvailableColumnsPanel.h" #include "AvailableColumnsPanel.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "ProcessList.h"
typedef struct CategoriesPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
Header* header;
ProcessList* pl;
} CategoriesPanel;
}*/
static const char* const CategoriesFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; static const char* const CategoriesFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
@ -48,9 +64,11 @@ static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
ScreenManager_add(this->scr, colors, -1); ScreenManager_add(this->scr, colors, -1);
} }
static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) { static void CategoriesPanel_makeScreensPage(CategoriesPanel* this) {
Panel* columns = (Panel*) ColumnsPanel_new(this->settings); Panel* screens = (Panel*) ScreensPanel_new(this->settings);
Panel* columns = (Panel*) ((ScreensPanel*)screens)->columns;
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns); Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns);
ScreenManager_add(this->scr, screens, 20);
ScreenManager_add(this->scr, columns, 20); ScreenManager_add(this->scr, columns, 20);
ScreenManager_add(this->scr, availableColumns, -1); ScreenManager_add(this->scr, availableColumns, -1);
} }
@ -102,7 +120,7 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
CategoriesPanel_makeColorsPage(this); CategoriesPanel_makeColorsPage(this);
break; break;
case 3: case 3:
CategoriesPanel_makeColumnsPage(this); CategoriesPanel_makeScreensPage(this);
break; break;
} }
} }
@ -127,10 +145,10 @@ CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Hea
this->settings = settings; this->settings = settings;
this->header = header; this->header = header;
this->pl = pl; this->pl = pl;
Panel_setHeader(super, "Setup"); Panel_setHeader(super, "Categories");
Panel_add(super, (Object*) ListItem_new("Meters", 0)); Panel_add(super, (Object*) ListItem_new("Meters", 0));
Panel_add(super, (Object*) ListItem_new("Display options", 0)); Panel_add(super, (Object*) ListItem_new("Display options", 0));
Panel_add(super, (Object*) ListItem_new("Colors", 0)); Panel_add(super, (Object*) ListItem_new("Colors", 0));
Panel_add(super, (Object*) ListItem_new("Columns", 0)); Panel_add(super, (Object*) ListItem_new("Screens", 0));
return this; return this;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CategoriesPanel #ifndef HEADER_CategoriesPanel
#define HEADER_CategoriesPanel #define HEADER_CategoriesPanel
/* /*
@ -21,6 +23,7 @@ typedef struct CategoriesPanel_ {
ProcessList* pl; ProcessList* pl;
} CategoriesPanel; } CategoriesPanel;
void CategoriesPanel_makeMetersPage(CategoriesPanel* this); void CategoriesPanel_makeMetersPage(CategoriesPanel* this);
extern PanelClass CategoriesPanel_class; extern PanelClass CategoriesPanel_class;

View File

@ -1,89 +1,3 @@
What's new in version 3.0.2
* BUGFIX: Drop 'vim_mode' - several issues, needs rethink
* BUGFIX: fix regression in -u optional-argument handling
* Build system rework to remove python, header generation
(thanks to Zev Weiss and Hugo Musso Gualandi)
* BUGFIX: report nice level correctly on Solaris
(thanks to Dominik Hassler)
* CI, code quality improvements
(thanks to Tobias Kortkamp, Christian Hesse, Benny Baumann)
What's new in version 3.0.1
* Coverity fixes, CI improvements, documentation updates
* BUGFIX: Fix early exit with longer sysfs battery paths
* BUGFIX: Improve OOM output, fix sorting
(thanks to Christian Göttsche)
* Rework check buttons and tree open/closed
(thanks to Bert Wesarg)
* Add -U/--no-unicode option to disable unicode
(thanks to Christian Hesse)
* Improvements to the affinity panel
(thanks to Bert Wesarg)
What's new in version 3.0.0
* New maintainers - after a prolonged period of inactivity
from Hisham, the creator and original maintainer, a team
of community maintainers have volunteered to take over a
fork at https://htop.dev and https://github.com/htop-dev
to keep the project going.
* Support ZFS ARC statistics
(thanks to Ross Williams)
* Support more than 2 smaller CPU meter columns
(thanks to Christoph Budziszewski)
* Support Linux proportional set size metrics
(thanks to @linvinus, @ntninja and @himikof)
* Support Linux pressure stall information metrics
(thanks to Ran Benita)
* New display option to show CPU frequency in CPU meters
(thanks to Arnav Singh)
* Update Linux sysfs battery discovery for recent kernels
(thanks to @smattie)
* Add hardware topology information in the affinity panel
(thanks to Bert Wesarg)
* Add timestamp reporting to the strace screen
(thanks to Mario Harjac)
* Add simple, optional vim key mapping mode
(thanks to Daniel Flanagan)
* Added an option to disable the mouse
(thanks to MartinJM)
* Add Solaris11 compatibility
(thanks to Jan Senolt)
* Without an argument -u uses $USER value automatically
(thanks to @solanav)
* Support less(1) search navigation shortcuts
(thanks to @syrrim)
* Update the FreeBSD maximum PID to match FreeBSD change
(thanks to @multiplexd)
* Report values larger than 100 terabytes
(thanks to @adrien1018)
* Widen ST_UID (UID) column to allow for UIDs > 9999
(thanks to DLange)
* BUGFIX: fix makefiles for building with clang
(thanks to Jorge Pereira)
* BUGFIX: fix <sys/sysmacros.h> major() usage
(thanks to @wataash and Kang-Che Sung)
* BUGFIX: fix the STARTTIME column on FreeBSD
(thanks to Rob Crowston)
* BUGFIX: truncate overwide jail names on FreeBSD
(thanks to Rob Crowston)
* BUGFIX: fix reported memory values on FreeBSD
(thanks to Tobias Kortkamp)
* BUGFIX: fix reported CPU meter values on OpenBSD
(thanks to @motet-a)
* BUGFIX: correctly identify other types of zombie process
(thanks to @joder)
* BUGFIX: improve follow-process handling in some situations
(thanks to @wangqr)
* BUGFIX: fix custom meters reverting to unexpected setting
(thanks to @wangqr)
* BUGFIX: close pipe after running lsof(1)
(thanks to Jesin)
* BUGFIX: meters honour setting of counting CPUs from 0/1
(thanks to @rnsanchez)
What's new in version 2.2.0 What's new in version 2.2.0
* Solaris/Illumos/OpenIndiana support * Solaris/Illumos/OpenIndiana support

View File

@ -12,6 +12,17 @@ in the source distribution for its full text.
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Object.h"
typedef struct CheckItem_ {
Object super;
char* text;
bool* ref;
bool value;
} CheckItem;
}*/
static void CheckItem_delete(Object* cast) { static void CheckItem_delete(Object* cast) {
CheckItem* this = (CheckItem*)cast; CheckItem* this = (CheckItem*)cast;

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CheckItem #ifndef HEADER_CheckItem
#define HEADER_CheckItem #define HEADER_CheckItem
/* /*
@ -16,6 +18,7 @@ typedef struct CheckItem_ {
bool value; bool value;
} CheckItem; } CheckItem;
extern ObjectClass CheckItem_class; extern ObjectClass CheckItem_class;
CheckItem* CheckItem_newByRef(char* text, bool* ref); CheckItem* CheckItem_newByRef(char* text, bool* ref);

View File

@ -11,6 +11,9 @@ in the source distribution for its full text.
#include <time.h> #include <time.h>
/*{
#include "Meter.h"
}*/
int ClockMeter_attributes[] = { int ClockMeter_attributes[] = {
CLOCK CLOCK

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ClockMeter #ifndef HEADER_ClockMeter
#define HEADER_ClockMeter #define HEADER_ClockMeter
/* /*

View File

@ -20,6 +20,19 @@ in the source distribution for its full text.
// * Add a define in CRT.h that matches the order of the array // * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors // * Add the colors in CRT_setColors
/*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct ColorsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColorsPanel;
}*/
static const char* const ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; static const char* const ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ColorsPanel #ifndef HEADER_ColorsPanel
#define HEADER_ColorsPanel #define HEADER_ColorsPanel
/* /*
@ -7,6 +9,12 @@ 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.
*/ */
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h
// * Add the entry in the ColorSchemeNames array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
#include "Panel.h" #include "Panel.h"
#include "Settings.h" #include "Settings.h"
#include "ScreenManager.h" #include "ScreenManager.h"
@ -18,6 +26,7 @@ typedef struct ColorsPanel_ {
ScreenManager* scr; ScreenManager* scr;
} ColorsPanel; } ColorsPanel;
extern PanelClass ColorsPanel_class; extern PanelClass ColorsPanel_class;
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr); ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr);

View File

@ -16,6 +16,19 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
/*{
#include "Panel.h"
#include "Settings.h"
typedef struct ColumnsPanel_ {
Panel super;
ScreenSettings* ss;
bool* changed;
bool moving;
} ColumnsPanel;
}*/
static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
@ -111,22 +124,31 @@ PanelClass ColumnsPanel_class = {
.eventHandler = ColumnsPanel_eventHandler .eventHandler = ColumnsPanel_eventHandler
}; };
ColumnsPanel* ColumnsPanel_new(Settings* settings) { void ColumnsPanel_fill(ColumnsPanel* this, ScreenSettings* ss) {
ColumnsPanel* this = AllocThis(ColumnsPanel);
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL); Panel_prune(super);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); ProcessField* fields = ss->fields;
this->settings = settings;
this->moving = false;
Panel_setHeader(super, "Active Columns");
ProcessField* fields = this->settings->fields;
for (; *fields; fields++) { for (; *fields; fields++) {
if (Process_fields[*fields].name) { if (Process_fields[*fields].name) {
Panel_add(super, (Object*) ListItem_new(Process_fields[*fields].name, *fields)); Panel_add(super, (Object*) ListItem_new(Process_fields[*fields].name, *fields));
} }
} }
this->ss = ss;
}
ColumnsPanel* ColumnsPanel_new(ScreenSettings* ss, bool* changed) {
ColumnsPanel* this = AllocThis(ColumnsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
this->ss = ss;
this->changed = changed;
this->moving = false;
Panel_setHeader(super, "Active Columns");
ColumnsPanel_fill(this, ss);
return this; return this;
} }
@ -142,13 +164,14 @@ int ColumnsPanel_fieldNameToIndex(const char* name) {
void ColumnsPanel_update(Panel* super) { void ColumnsPanel_update(Panel* super) {
ColumnsPanel* this = (ColumnsPanel*) super; ColumnsPanel* this = (ColumnsPanel*) super;
int size = Panel_size(super); int size = Panel_size(super);
this->settings->changed = true; *(this->changed) = true;
this->settings->fields = xRealloc(this->settings->fields, sizeof(ProcessField) * (size+1)); this->ss->fields = xRealloc(this->ss->fields, sizeof(ProcessField) * (size+1));
this->settings->flags = 0; this->ss->flags = 0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
int key = ((ListItem*) Panel_get(super, i))->key; int key = ((ListItem*) Panel_get(super, i))->key;
this->settings->fields[i] = key; this->ss->fields[i] = key;
this->settings->flags |= Process_fields[key].flags; this->ss->flags |= key < 1000 ? Process_fields[key].flags : 0;
} }
this->settings->fields[size] = 0; this->ss->fields[size] = 0;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ColumnsPanel #ifndef HEADER_ColumnsPanel
#define HEADER_ColumnsPanel #define HEADER_ColumnsPanel
/* /*
@ -12,17 +14,22 @@ in the source distribution for its full text.
typedef struct ColumnsPanel_ { typedef struct ColumnsPanel_ {
Panel super; Panel super;
ScreenSettings* ss;
bool* changed;
Settings* settings;
bool moving; bool moving;
} ColumnsPanel; } ColumnsPanel;
extern PanelClass ColumnsPanel_class; extern PanelClass ColumnsPanel_class;
ColumnsPanel* ColumnsPanel_new(Settings* settings); void ColumnsPanel_fill(ColumnsPanel* this, ScreenSettings* ss);
ColumnsPanel* ColumnsPanel_new(ScreenSettings* ss, bool* changed);
int ColumnsPanel_fieldNameToIndex(const char* name); int ColumnsPanel_fieldNameToIndex(const char* name);
void ColumnsPanel_update(Panel* super); void ColumnsPanel_update(Panel* super);
#endif #endif

View File

@ -14,6 +14,19 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct DisplayOptionsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} DisplayOptionsPanel;
}*/
static const char* const DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; static const char* const DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
@ -70,7 +83,6 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
this->scr = scr; this->scr = scr;
Panel_setHeader(super, "Display options"); Panel_setHeader(super, "Display options");
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Tree view"), &(settings->treeView)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Shadow other users' processes"), &(settings->shadowOtherUsers))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Shadow other users' processes"), &(settings->shadowOtherUsers)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Hide kernel threads"), &(settings->hideKernelThreads))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Hide kernel threads"), &(settings->hideKernelThreads)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Hide userland process threads"), &(settings->hideUserlandThreads))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Hide userland process threads"), &(settings->hideUserlandThreads)));
@ -84,11 +96,6 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Count CPUs from 0 instead of 1"), &(settings->countCPUsFromZero))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Count CPUs from 0 instead of 1"), &(settings->countCPUsFromZero)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Update process names on every refresh"), &(settings->updateProcessNames))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Update process names on every refresh"), &(settings->updateProcessNames)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Add guest time in CPU meter percentage"), &(settings->accountGuestInCPUMeter))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Add guest time in CPU meter percentage"), &(settings->accountGuestInCPUMeter)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show tabs for screens"), &(settings->screenTabs)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency)));
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
#ifdef HAVE_LIBHWLOC
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity)));
#endif
return this; return this;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DisplayOptionsPanel #ifndef HEADER_DisplayOptionsPanel
#define HEADER_DisplayOptionsPanel #define HEADER_DisplayOptionsPanel
/* /*
@ -18,6 +20,7 @@ typedef struct DisplayOptionsPanel_ {
ScreenManager* scr; ScreenManager* scr;
} DisplayOptionsPanel; } DisplayOptionsPanel;
extern PanelClass DisplayOptionsPanel_class; extern PanelClass DisplayOptionsPanel_class;
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr); DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr);

View File

@ -11,6 +11,13 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
/*{
#include "InfoScreen.h"
typedef struct EnvScreen_ {
InfoScreen super;
} EnvScreen;
}*/
InfoScreenClass EnvScreen_class = { InfoScreenClass EnvScreen_class = {
.super = { .super = {
@ -37,7 +44,7 @@ void EnvScreen_draw(InfoScreen* this) {
void EnvScreen_scan(InfoScreen* this) { void EnvScreen_scan(InfoScreen* this) {
Panel* panel = this->display; Panel* panel = this->display;
int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); int idx = MAX(Panel_getSelectedIndex(panel), 0);
Panel_prune(panel); Panel_prune(panel);

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_EnvScreen #ifndef HEADER_EnvScreen
#define HEADER_EnvScreen #define HEADER_EnvScreen

View File

@ -14,6 +14,19 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include <stdbool.h>
typedef struct FunctionBar_ {
int size;
char** functions;
char** keys;
int* events;
bool staticData;
} FunctionBar;
}*/
static const char* const FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL}; static const char* const FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL};
@ -83,11 +96,12 @@ void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) {
} }
} }
void FunctionBar_draw(const FunctionBar* this, char* buffer) { int FunctionBar_draw(const FunctionBar* this, char* buffer) {
FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]); return FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]);
} }
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) { int FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) {
int cursorX = 0;
attrset(CRT_colors[FUNCTION_BAR]); attrset(CRT_colors[FUNCTION_BAR]);
mvhline(LINES-1, 0, ' ', COLS); mvhline(LINES-1, 0, ' ', COLS);
int x = 0; int x = 0;
@ -102,12 +116,10 @@ void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr) {
if (buffer) { if (buffer) {
attrset(attr); attrset(attr);
mvaddstr(LINES-1, x, buffer); mvaddstr(LINES-1, x, buffer);
CRT_cursorX = x + strlen(buffer); cursorX = x + strlen(buffer);
curs_set(1);
} else {
curs_set(0);
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
return cursorX;
} }
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) { int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) {

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_FunctionBar #ifndef HEADER_FunctionBar
#define HEADER_FunctionBar #define HEADER_FunctionBar
/* /*
@ -7,6 +9,7 @@ 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 <stdbool.h> #include <stdbool.h>
typedef struct FunctionBar_ { typedef struct FunctionBar_ {
@ -17,6 +20,8 @@ typedef struct FunctionBar_ {
bool staticData; bool staticData;
} FunctionBar; } FunctionBar;
FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc); FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc);
FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events); FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events);
@ -25,9 +30,9 @@ void FunctionBar_delete(FunctionBar* this);
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text); void FunctionBar_setLabel(FunctionBar* this, int event, const char* text);
void FunctionBar_draw(const FunctionBar* this, char* buffer); int FunctionBar_draw(const FunctionBar* this, char* buffer);
void FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr); int FunctionBar_drawAttr(const FunctionBar* this, char* buffer, int attr);
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos); int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos);

View File

@ -11,6 +11,26 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
/*{
#include <stdbool.h>
typedef struct Hashtable_ Hashtable;
typedef void(*Hashtable_PairFunction)(int, void*, void*);
typedef struct HashtableItem {
unsigned int key;
void* value;
struct HashtableItem* next;
} HashtableItem;
struct Hashtable_ {
int size;
HashtableItem** buckets;
int items;
bool owner;
};
}*/
#ifdef DEBUG #ifdef DEBUG

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Hashtable #ifndef HEADER_Hashtable
#define HEADER_Hashtable #define HEADER_Hashtable
/* /*
@ -40,7 +42,7 @@ void Hashtable_put(Hashtable* this, unsigned int key, void* value);
void* Hashtable_remove(Hashtable* this, unsigned int key); void* Hashtable_remove(Hashtable* this, unsigned int key);
void* Hashtable_get(Hashtable* this, unsigned int key); extern void* Hashtable_get(Hashtable* this, unsigned int key);
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData); void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);

View File

@ -16,6 +16,30 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Meter.h"
#include "Settings.h"
#include "Vector.h"
typedef struct Header_ {
Vector** columns;
Settings* settings;
struct ProcessList_* pl;
int nrColumns;
int pad;
int height;
} Header;
}*/
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef Header_forEachColumn
#define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_))
#endif
Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns) { Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns) {
Header* this = xCalloc(1, sizeof(Header)); Header* this = xCalloc(1, sizeof(Header));
this->columns = xCalloc(nrColumns, sizeof(Vector*)); this->columns = xCalloc(nrColumns, sizeof(Vector*));
@ -38,7 +62,7 @@ void Header_delete(Header* this) {
void Header_populateFromSettings(Header* this) { void Header_populateFromSettings(Header* this) {
Header_forEachColumn(this, col) { Header_forEachColumn(this, col) {
MeterColumnSettings* colSettings = &this->settings->columns[col]; MeterColumnSettings* colSettings = &this->settings->meterColumns[col];
for (int i = 0; i < colSettings->len; i++) { for (int i = 0; i < colSettings->len; i++) {
Header_addMeterByName(this, colSettings->names[i], col); Header_addMeterByName(this, colSettings->names[i], col);
if (colSettings->modes[i] != 0) { if (colSettings->modes[i] != 0) {
@ -51,7 +75,7 @@ void Header_populateFromSettings(Header* this) {
void Header_writeBackToSettings(const Header* this) { void Header_writeBackToSettings(const Header* this) {
Header_forEachColumn(this, col) { Header_forEachColumn(this, col) {
MeterColumnSettings* colSettings = &this->settings->columns[col]; MeterColumnSettings* colSettings = &this->settings->meterColumns[col];
String_freeArray(colSettings->names); String_freeArray(colSettings->names);
free(colSettings->modes); free(colSettings->modes);
@ -96,8 +120,6 @@ MeterModeId Header_addMeterByName(Header* this, char* name, int column) {
break; break;
} }
} }
if (paren)
*paren = '(';
return mode; return mode;
} }
@ -130,7 +152,7 @@ char* Header_readMeterName(Header* this, int i, int column) {
int nameLen = strlen(Meter_name(meter)); int nameLen = strlen(Meter_name(meter));
int len = nameLen + 100; int len = nameLen + 100;
char* name = xMalloc(len); char* name = xMalloc(len);
memcpy(name, Meter_name(meter), nameLen); strncpy(name, Meter_name(meter), nameLen);
name[nameLen] = '\0'; name[nameLen] = '\0';
if (meter->param) if (meter->param)
xSnprintf(name + nameLen, len - nameLen, "(%d)", meter->param); xSnprintf(name + nameLen, len - nameLen, "(%d)", meter->param);
@ -187,7 +209,10 @@ int Header_calculateHeight(Header* this) {
Meter* meter = (Meter*) Vector_get(meters, i); Meter* meter = (Meter*) Vector_get(meters, i);
height += meter->h; height += meter->h;
} }
maxHeight = MAXIMUM(maxHeight, height); maxHeight = MAX(maxHeight, height);
}
if (this->settings->screenTabs) {
maxHeight++;
} }
this->height = maxHeight; this->height = maxHeight;
this->pad = pad; this->pad = pad;

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Header #ifndef HEADER_Header
#define HEADER_Header #define HEADER_Header
/* /*
@ -20,7 +22,14 @@ typedef struct Header_ {
int height; int height;
} Header; } Header;
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef Header_forEachColumn
#define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_)) #define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_))
#endif
Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns); Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns);

View File

@ -11,6 +11,9 @@ in the source distribution for its full text.
#include <unistd.h> #include <unistd.h>
/*{
#include "Meter.h"
}*/
int HostnameMeter_attributes[] = { int HostnameMeter_attributes[] = {
HOSTNAME HOSTNAME

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_HostnameMeter #ifndef HEADER_HostnameMeter
#define HEADER_HostnameMeter #define HEADER_HostnameMeter
/* /*

111
IncSet.c
View File

@ -7,21 +7,52 @@ in the source distribution for its full text.
#include "IncSet.h" #include "IncSet.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "Panel.h"
#include "ListItem.h" #include "ListItem.h"
#include "CRT.h" #include "CRT.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "FunctionBar.h"
#include "Panel.h"
#include <stdbool.h>
#define INCMODE_MAX 40
typedef enum {
INC_SEARCH = 0,
INC_FILTER = 1
} IncType;
#define IncSet_filter(inc_) (inc_->filtering ? inc_->modes[INC_FILTER].buffer : NULL)
typedef struct IncMode_ {
char buffer[INCMODE_MAX+1];
int index;
FunctionBar* bar;
bool isFilter;
} IncMode;
typedef struct IncSet_ {
IncMode modes[2];
IncMode* active;
Panel* panel;
FunctionBar* defaultBar;
bool filtering;
bool found;
} IncSet;
typedef const char* (*IncMode_GetPanelValue)(Panel*, int);
}*/
static void IncMode_reset(IncMode* mode) { static void IncMode_reset(IncMode* mode) {
mode->index = 0; mode->index = 0;
mode->buffer[0] = 0; mode->buffer[0] = 0;
} }
void IncSet_reset(IncSet* this, IncType type) {
IncMode_reset(&this->modes[type]);
}
static const char* const searchFunctions[] = {"Next ", "Cancel ", " Search: ", NULL}; static const char* const searchFunctions[] = {"Next ", "Cancel ", " Search: ", NULL};
static const char* const searchKeys[] = {"F3", "Esc", " "}; static const char* const searchKeys[] = {"F3", "Esc", " "};
static int searchEvents[] = {KEY_F(3), 27, ERR}; static int searchEvents[] = {KEY_F(3), 27, ERR};
@ -85,45 +116,33 @@ static void updateWeakPanel(IncSet* this, Panel* panel, Vector* lines) {
} }
} }
static bool search(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) { static bool search(IncSet* this, Panel* panel, IncMode_GetPanelValue getPanelValue) {
int size = Panel_size(panel); int size = Panel_size(panel);
bool found = false; bool found = false;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { if (String_contains_i(getPanelValue(panel, i), this->active->buffer)) {
Panel_setSelected(panel, i); Panel_setSelected(panel, i);
found = true; found = true;
break; break;
} }
} }
if (found) IncSet_drawBar(this, found ? CRT_colors[FUNCTION_BAR] : CRT_colors[FAILED_SEARCH]);
FunctionBar_draw(mode->bar, mode->buffer);
else
FunctionBar_drawAttr(mode->bar, mode->buffer, CRT_colors[FAILED_SEARCH]);
return found; return found;
} }
static bool IncMode_find(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) { void IncSet_activate(IncSet* this, IncType type, Panel* panel) {
int size = Panel_size(panel); this->active = &(this->modes[type]);
int here = Panel_getSelectedIndex(panel); panel->currentBar = this->active->bar;
int i = here; panel->cursorOn = true;
for(;;) { this->panel = panel;
i+=step; IncSet_drawBar(this, CRT_colors[FUNCTION_BAR]);
if (i == size) i = 0;
if (i == -1) i = size - 1;
if (i == here) return false;
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
return true;
}
}
} }
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) { static void IncSet_deactivate(IncSet* this, Panel* panel) {
return IncMode_find(&this->modes[type], panel, getPanelValue, 1); this->active = NULL;
} Panel_setDefaultBar(panel);
panel->cursorOn = false;
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) { FunctionBar_draw(this->defaultBar, NULL);
return IncMode_find(&this->modes[type], panel, getPanelValue, -1);
} }
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) { bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
@ -135,7 +154,17 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
bool doSearch = true; bool doSearch = true;
if (ch == KEY_F(3)) { if (ch == KEY_F(3)) {
if (size == 0) return true; if (size == 0) return true;
IncMode_find(mode, panel, getPanelValue, 1); int here = Panel_getSelectedIndex(panel);
int i = here;
for(;;) {
i++;
if (i == size) i = 0;
if (i == here) break;
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
break;
}
}
doSearch = false; doSearch = false;
} else if (ch < 255 && isprint((char)ch)) { } else if (ch < 255 && isprint((char)ch)) {
if (mode->index < INCMODE_MAX) { if (mode->index < INCMODE_MAX) {
@ -171,17 +200,13 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
IncMode_reset(mode); IncMode_reset(mode);
} }
} else { } else {
if (ch == 27) {
IncMode_reset(mode); IncMode_reset(mode);
} }
} IncSet_deactivate(this, panel);
this->active = NULL;
Panel_setDefaultBar(panel);
FunctionBar_draw(this->defaultBar, NULL);
doSearch = false; doSearch = false;
} }
if (doSearch) { if (doSearch) {
this->found = search(mode, panel, getPanelValue); this->found = search(this, panel, getPanelValue);
} }
if (filterChanged && lines) { if (filterChanged && lines) {
updateWeakPanel(this, panel, lines); updateWeakPanel(this, panel, lines);
@ -196,15 +221,11 @@ const char* IncSet_getListItemValue(Panel* panel, int i) {
return ""; return "";
} }
void IncSet_activate(IncSet* this, IncType type, Panel* panel) { void IncSet_drawBar(IncSet* this, int attr) {
this->active = &(this->modes[type]);
FunctionBar_draw(this->active->bar, this->active->buffer);
panel->currentBar = this->active->bar;
}
void IncSet_drawBar(IncSet* this) {
if (this->active) { if (this->active) {
FunctionBar_draw(this->active->bar, this->active->buffer); int cursorX = FunctionBar_drawAttr(this->active->bar, this->active->buffer, attr);
this->panel->cursorY = LINES - 1;
this->panel->cursorX = cursorX;
} else { } else {
FunctionBar_draw(this->defaultBar, NULL); FunctionBar_draw(this->defaultBar, NULL);
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_IncSet #ifndef HEADER_IncSet
#define HEADER_IncSet #define HEADER_IncSet
/* /*
@ -7,6 +9,7 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "FunctionBar.h" #include "FunctionBar.h"
#include "Panel.h" #include "Panel.h"
#include <stdbool.h> #include <stdbool.h>
@ -30,6 +33,7 @@ typedef struct IncMode_ {
typedef struct IncSet_ { typedef struct IncSet_ {
IncMode modes[2]; IncMode modes[2];
IncMode* active; IncMode* active;
Panel* panel;
FunctionBar* defaultBar; FunctionBar* defaultBar;
bool filtering; bool filtering;
bool found; bool found;
@ -37,23 +41,18 @@ typedef struct IncSet_ {
typedef const char* (*IncMode_GetPanelValue)(Panel*, int); typedef const char* (*IncMode_GetPanelValue)(Panel*, int);
void IncSet_reset(IncSet* this, IncType type);
IncSet* IncSet_new(FunctionBar* bar); IncSet* IncSet_new(FunctionBar* bar);
void IncSet_delete(IncSet* this); void IncSet_delete(IncSet* this);
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue); void IncSet_activate(IncSet* this, IncType type, Panel* panel);
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue);
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines); bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
const char* IncSet_getListItemValue(Panel* panel, int i); const char* IncSet_getListItemValue(Panel* panel, int i);
void IncSet_activate(IncSet* this, IncType type, Panel* panel); void IncSet_drawBar(IncSet* this, int attr);
void IncSet_drawBar(IncSet* this);
int IncSet_synthesizeEvent(IncSet* this, int x); int IncSet_synthesizeEvent(IncSet* this, int x);

View File

@ -13,6 +13,42 @@
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
/*{
#include "Process.h"
#include "Panel.h"
#include "FunctionBar.h"
#include "IncSet.h"
typedef struct InfoScreen_ InfoScreen;
typedef void(*InfoScreen_Scan)(InfoScreen*);
typedef void(*InfoScreen_Draw)(InfoScreen*);
typedef void(*InfoScreen_OnErr)(InfoScreen*);
typedef bool(*InfoScreen_OnKey)(InfoScreen*, int);
typedef struct InfoScreenClass_ {
ObjectClass super;
const InfoScreen_Scan scan;
const InfoScreen_Draw draw;
const InfoScreen_OnErr onErr;
const InfoScreen_OnKey onKey;
} InfoScreenClass;
#define As_InfoScreen(this_) ((InfoScreenClass*)(((InfoScreen*)(this_))->super.klass))
#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_))
#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_))
#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_))
#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_)
struct InfoScreen_ {
Object super;
Process* process;
Panel* display;
FunctionBar* bar;
IncSet* inc;
Vector* lines;
};
}*/
static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL};
@ -20,7 +56,7 @@ static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"};
static int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; static int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, const char* panelHeader) { InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, char* panelHeader) {
this->process = process; this->process = process;
if (!bar) { if (!bar) {
bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents); bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
@ -39,17 +75,17 @@ InfoScreen* InfoScreen_done(InfoScreen* this) {
return this; return this;
} }
void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) { void InfoScreen_drawTitled(InfoScreen* this, char* fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
attrset(CRT_colors[METER_TEXT]); attrset(CRT_colors[METER_TEXT]);
mvhline(0, 0, ' ', COLS); mvhline(0, 0, ' ', COLS);
(void) wmove(stdscr, 0, 0); wmove(stdscr, 0, 0);
vw_printw(stdscr, fmt, ap); vw_printw(stdscr, fmt, ap);
attrset(CRT_colors[DEFAULT_COLOR]); attrset(CRT_colors[DEFAULT_COLOR]);
this->display->needsRedraw = true; this->display->needsRedraw = true;
Panel_draw(this->display, true); Panel_draw(this->display, true);
IncSet_drawBar(this->inc); IncSet_drawBar(this->inc, CRT_colors[FUNCTION_BAR]);
va_end(ap); va_end(ap);
} }
@ -79,11 +115,7 @@ void InfoScreen_run(InfoScreen* this) {
Panel_draw(panel, true); Panel_draw(panel, true);
if (this->inc->active) { int ch = Panel_getCh(panel);
(void) move(LINES-1, CRT_cursorX);
}
set_escdelay(25);
int ch = getch();
if (ch == ERR) { if (ch == ERR) {
if (As_InfoScreen(this)->onErr) { if (As_InfoScreen(this)->onErr) {
@ -95,15 +127,13 @@ void InfoScreen_run(InfoScreen* this) {
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 >= panel->y && mevent.y < LINES - 1) { if (mevent.y >= panel->y && mevent.y < LINES - 1) {
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV); Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
ch = 0; ch = 0;
} else if (mevent.y == LINES - 1) { } if (mevent.y == LINES - 1)
ch = IncSet_synthesizeEvent(this->inc, mevent.x); ch = IncSet_synthesizeEvent(this->inc, mevent.x);
} }
}
}
if (this->inc->active) { if (this->inc->active) {
IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines); IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines);

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_InfoScreen #ifndef HEADER_InfoScreen
#define HEADER_InfoScreen #define HEADER_InfoScreen
@ -36,11 +38,11 @@ struct InfoScreen_ {
Vector* lines; Vector* lines;
}; };
InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, const char* panelHeader); InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, char* panelHeader);
InfoScreen* InfoScreen_done(InfoScreen* this); InfoScreen* InfoScreen_done(InfoScreen* this);
void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...); void InfoScreen_drawTitled(InfoScreen* this, char* fmt, ...);
void InfoScreen_addLine(InfoScreen* this, const char* line); void InfoScreen_addLine(InfoScreen* this, const char* line);

View File

@ -15,14 +15,25 @@ in the source distribution for its full text.
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Object.h"
static void ListItem_delete(Object* cast) { typedef struct ListItem_ {
Object super;
char* value;
int key;
bool moving;
} ListItem;
}*/
void ListItem_delete(Object* cast) {
ListItem* this = (ListItem*)cast; ListItem* this = (ListItem*)cast;
free(this->value); free(this->value);
free(this); free(this);
} }
static void ListItem_display(Object* cast, RichString* out) { void ListItem_display(Object* cast, RichString* out) {
ListItem* const this = (ListItem*)cast; ListItem* const this = (ListItem*)cast;
assert (this != NULL); assert (this != NULL);
/* /*
@ -48,11 +59,15 @@ ObjectClass ListItem_class = {
.compare = ListItem_compare .compare = ListItem_compare
}; };
ListItem* ListItem_new(const char* value, int key) { void ListItem_init(ListItem* this, const char* value, int key) {
ListItem* this = AllocThis(ListItem);
this->value = xStrdup(value); this->value = xStrdup(value);
this->key = key; this->key = key;
this->moving = false; this->moving = false;
}
ListItem* ListItem_new(const char* value, int key) {
ListItem* this = AllocThis(ListItem);
ListItem_init(this, value, key);
return this; return this;
} }
@ -74,3 +89,4 @@ long ListItem_compare(const void* cast1, const void* cast2) {
ListItem* obj2 = (ListItem*) cast2; ListItem* obj2 = (ListItem*) cast2;
return strcmp(obj1->value, obj2->value); return strcmp(obj1->value, obj2->value);
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ListItem #ifndef HEADER_ListItem
#define HEADER_ListItem #define HEADER_ListItem
/* /*
@ -16,8 +18,15 @@ typedef struct ListItem_ {
bool moving; bool moving;
} ListItem; } ListItem;
void ListItem_delete(Object* cast);
void ListItem_display(Object* cast, RichString* out);
extern ObjectClass ListItem_class; extern ObjectClass ListItem_class;
void ListItem_init(ListItem* this, const char* value, int key);
ListItem* ListItem_new(const char* value, int key); ListItem* ListItem_new(const char* value, int key);
void ListItem_append(ListItem* this, const char* text); void ListItem_append(ListItem* this, const char* text);
@ -26,4 +35,5 @@ const char* ListItem_getRef(ListItem* this);
long ListItem_compare(const void* cast1, const void* cast2); long ListItem_compare(const void* cast1, const void* cast2);
#endif #endif

View File

@ -10,6 +10,9 @@ in the source distribution for its full text.
#include "CRT.h" #include "CRT.h"
#include "Platform.h" #include "Platform.h"
/*{
#include "Meter.h"
}*/
int LoadAverageMeter_attributes[] = { int LoadAverageMeter_attributes[] = {
LOAD_AVERAGE_ONE, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_FIFTEEN LOAD_AVERAGE_ONE, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_FIFTEEN

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_LoadAverageMeter #ifndef HEADER_LoadAverageMeter
#define HEADER_LoadAverageMeter #define HEADER_LoadAverageMeter
/* /*

View File

@ -1,16 +0,0 @@
#ifndef HEADER_Macros
#define HEADER_Macros
#ifndef MINIMUM
#define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAXIMUM
#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : MAXIMUM(x, low))
#endif
#endif

View File

@ -1,7 +1,6 @@
/* /*
htop - ColumnsPanel.c htop - ColumnsPanel.c
(C) 2004-2015 Hisham H. Muhammad (C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
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.
*/ */
@ -13,6 +12,30 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
/*{
#include "Panel.h"
#include "Action.h"
#include "Settings.h"
typedef struct MainPanel_ {
Panel super;
State* state;
IncSet* inc;
Htop_Action *keys;
pid_t pidSearch;
} MainPanel;
typedef union {
int i;
void* v;
} Arg;
typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg);
#define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar)
}*/
static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL}; static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL};
void MainPanel_updateTreeFunctions(MainPanel* this, bool mode) { void MainPanel_updateTreeFunctions(MainPanel* this, bool mode) {
@ -49,20 +72,26 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
Htop_Reaction reaction = HTOP_OK; Htop_Reaction reaction = HTOP_OK;
Settings* settings = this->state->settings;
ScreenSettings* ss = settings->ss;
if (EVENT_IS_HEADER_CLICK(ch)) { if (EVENT_IS_HEADER_CLICK(ch)) {
int x = EVENT_HEADER_CLICK_GET_X(ch); int x = EVENT_HEADER_CLICK_GET_X(ch);
ProcessList* pl = this->state->pl; ProcessList* pl = this->state->pl;
Settings* settings = this->state->settings;
int hx = super->scrollH + x + 1; int hx = super->scrollH + x + 1;
ProcessField field = ProcessList_keyAt(pl, hx); ProcessField field = ProcessList_keyAt(pl, hx);
if (field == settings->sortKey) { if (field == ss->sortKey) {
Settings_invertSortOrder(settings); ScreenSettings_invertSortOrder(ss);
settings->treeView = false; ss->treeView = false;
} else { } else {
reaction |= Action_setSortKey(settings, field); reaction |= Action_setSortKey(settings, field);
} }
reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS; reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS;
result = HANDLED; result = HANDLED;
} else if (EVENT_IS_SCREEN_TAB_CLICK(ch)) {
int x = EVENT_SCREEN_TAB_GET_X(ch);
reaction |= Action_setScreenTab(settings, x);
result = HANDLED;
} else if (ch != ERR && this->inc->active) { } else if (ch != ERR && this->inc->active) {
bool filterChanged = IncSet_handleKey(this->inc, ch, super, (IncMode_GetPanelValue) MainPanel_getValue, NULL); bool filterChanged = IncSet_handleKey(this->inc, ch, super, (IncMode_GetPanelValue) MainPanel_getValue, NULL);
if (filterChanged) { if (filterChanged) {
@ -90,8 +119,8 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
} }
if (reaction & HTOP_REDRAW_BAR) { if (reaction & HTOP_REDRAW_BAR) {
MainPanel_updateTreeFunctions(this, this->state->settings->treeView); MainPanel_updateTreeFunctions(this, settings->ss->treeView);
IncSet_drawBar(this->inc); IncSet_drawBar(this->inc, CRT_colors[FUNCTION_BAR]);
} }
if (reaction & HTOP_UPDATE_PANELHDR) { if (reaction & HTOP_UPDATE_PANELHDR) {
ProcessList_printHeader(this->state->pl, Panel_getHeader(super)); ProcessList_printHeader(this->state->pl, Panel_getHeader(super));

View File

@ -1,16 +1,17 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MainPanel #ifndef HEADER_MainPanel
#define HEADER_MainPanel #define HEADER_MainPanel
/* /*
htop - ColumnsPanel.h htop - ColumnsPanel.h
(C) 2004-2015 Hisham H. Muhammad (C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Action.h"
#include "IncSet.h"
#include "Panel.h" #include "Panel.h"
#include "Action.h"
#include "Settings.h"
typedef struct MainPanel_ { typedef struct MainPanel_ {
Panel super; Panel super;
@ -20,10 +21,16 @@ typedef struct MainPanel_ {
pid_t pidSearch; pid_t pidSearch;
} MainPanel; } MainPanel;
typedef union {
int i;
void* v;
} Arg;
typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg); typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg);
#define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar) #define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar)
void MainPanel_updateTreeFunctions(MainPanel* this, bool mode); void MainPanel_updateTreeFunctions(MainPanel* this, bool mode);
void MainPanel_pidSearch(MainPanel* this, int ch); void MainPanel_pidSearch(MainPanel* this, int ch);

View File

@ -5,14 +5,14 @@ AUTOMAKE_OPTIONS = subdir-objects
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 \ EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py \
install-sh autogen.sh missing 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 $(wextra_flag) -std=c99 -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\" -I"$(top_srcdir)/$(my_htop_platform)" AM_CFLAGS = -pedantic -Wall $(wextra_flag) -std=c99 -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\" -I"$(top_srcdir)/$(my_htop_platform)"
AM_LDFLAGS = AM_LDFLAGS =
AM_CPPFLAGS = -DNDEBUG AM_CPPFLAGS = -DNDEBUG
@ -21,7 +21,7 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c MainPanel.c \
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \ DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \ SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c ScreensPanel.c \
TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \ HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \
InfoScreen.c XAlloc.c InfoScreen.c XAlloc.c
@ -29,12 +29,14 @@ InfoScreen.c XAlloc.c
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \ myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
CPUMeter.h CRT.h MainPanel.h DisplayOptionsPanel.h FunctionBar.h \ CPUMeter.h CRT.h MainPanel.h DisplayOptionsPanel.h FunctionBar.h \
Hashtable.h Header.h ListItem.h LoadAverageMeter.h MemoryMeter.h \ Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \ ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h ScreensPanel.h \
TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \ TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \
AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \ AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \
EnvScreen.h InfoScreen.h XAlloc.h Macros.h EnvScreen.h InfoScreen.h XAlloc.h
all_platform_headers =
# Linux # Linux
# ----- # -----
@ -47,17 +49,15 @@ linux_platform_headers = \
linux/LinuxProcessList.h \ linux/LinuxProcessList.h \
linux/LinuxCRT.h \ linux/LinuxCRT.h \
linux/Battery.h \ linux/Battery.h \
linux/PressureStallMeter.h \ linux/PerfCounter.h
zfs/ZfsArcMeter.h \
zfs/ZfsCompressedArcMeter.h \ all_platform_headers += $(linux_platform_headers)
zfs/ZfsArcStats.h
if HTOP_LINUX if HTOP_LINUX
AM_LDFLAGS += -rdynamic AM_CFLAGS += -rdynamic
myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c \ myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c \ linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c \
linux/PressureStallMeter.c \ linux/PerfCounter.c
zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c
myhtopplatheaders = $(linux_platform_headers) myhtopplatheaders = $(linux_platform_headers)
endif endif
@ -70,16 +70,13 @@ freebsd_platform_headers = \
freebsd/FreeBSDProcessList.h \ freebsd/FreeBSDProcessList.h \
freebsd/FreeBSDProcess.h \ freebsd/FreeBSDProcess.h \
freebsd/FreeBSDCRT.h \ freebsd/FreeBSDCRT.h \
freebsd/Battery.h \ freebsd/Battery.h
zfs/ZfsArcMeter.h \
zfs/ZfsCompressedArcMeter.h \ all_platform_headers += $(freebsd_platform_headers)
zfs/ZfsArcStats.h \
zfs/openzfs_sysctl.h
if HTOP_FREEBSD if HTOP_FREEBSD
myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \ myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \
freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c \ freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c
zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c
myhtopplatheaders = $(freebsd_platform_headers) myhtopplatheaders = $(freebsd_platform_headers)
endif endif
@ -94,6 +91,8 @@ dragonflybsd_platform_headers = \
dragonflybsd/DragonFlyBSDCRT.h \ dragonflybsd/DragonFlyBSDCRT.h \
dragonflybsd/Battery.h dragonflybsd/Battery.h
all_platform_headers += $(dragonflybsd_platform_headers)
if HTOP_DRAGONFLYBSD if HTOP_DRAGONFLYBSD
AM_LDFLAGS += -lkvm -lkinfo -lexecinfo AM_LDFLAGS += -lkvm -lkinfo -lexecinfo
myhtopplatsources = dragonflybsd/Platform.c dragonflybsd/DragonFlyBSDProcessList.c \ myhtopplatsources = dragonflybsd/Platform.c dragonflybsd/DragonFlyBSDProcessList.c \
@ -112,6 +111,8 @@ openbsd_platform_headers = \
openbsd/OpenBSDCRT.h \ openbsd/OpenBSDCRT.h \
openbsd/Battery.h openbsd/Battery.h
all_platform_headers += $(openbsd_platform_headers)
if HTOP_OPENBSD if HTOP_OPENBSD
myhtopplatsources = openbsd/Platform.c openbsd/OpenBSDProcessList.c \ myhtopplatsources = openbsd/Platform.c openbsd/OpenBSDProcessList.c \
openbsd/OpenBSDProcess.c openbsd/OpenBSDCRT.c openbsd/Battery.c openbsd/OpenBSDProcess.c openbsd/OpenBSDCRT.c openbsd/Battery.c
@ -127,17 +128,14 @@ darwin_platform_headers = \
darwin/DarwinProcess.h \ darwin/DarwinProcess.h \
darwin/DarwinProcessList.h \ darwin/DarwinProcessList.h \
darwin/DarwinCRT.h \ darwin/DarwinCRT.h \
darwin/Battery.h \ darwin/Battery.h
zfs/ZfsArcMeter.h \
zfs/ZfsCompressedArcMeter.h \ all_platform_headers += $(darwin_platform_headers)
zfs/ZfsArcStats.h \
zfs/openzfs_sysctl.h
if HTOP_DARWIN if HTOP_DARWIN
AM_LDFLAGS += -framework IOKit -framework CoreFoundation AM_LDFLAGS += -framework IOKit -framework CoreFoundation
myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \
darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c \ darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c
zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c
myhtopplatheaders = $(darwin_platform_headers) myhtopplatheaders = $(darwin_platform_headers)
endif endif
@ -150,16 +148,14 @@ solaris_platform_headers = \
solaris/SolarisProcess.h \ solaris/SolarisProcess.h \
solaris/SolarisProcessList.h \ solaris/SolarisProcessList.h \
solaris/SolarisCRT.h \ solaris/SolarisCRT.h \
solaris/Battery.h \ solaris/Battery.h
zfs/ZfsArcMeter.h \
zfs/ZfsCompressedArcMeter.h \ all_platform_headers += $(solaris_platform_headers)
zfs/ZfsArcStats.h
if HTOP_SOLARIS if HTOP_SOLARIS
myhtopplatsources = solaris/Platform.c \ myhtopplatsources = solaris/Platform.c \
solaris/SolarisProcess.c solaris/SolarisProcessList.c \ solaris/SolarisProcess.c solaris/SolarisProcessList.c \
solaris/SolarisCRT.c solaris/Battery.c \ solaris/SolarisCRT.c solaris/Battery.c
zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c
myhtopplatheaders = $(solaris_platform_headers) myhtopplatheaders = $(solaris_platform_headers)
endif endif
@ -174,6 +170,8 @@ unsupported_platform_headers = \
unsupported/UnsupportedCRT.h \ unsupported/UnsupportedCRT.h \
unsupported/Battery.h unsupported/Battery.h
all_platform_headers += $(unsupported_platform_headers)
if HTOP_UNSUPPORTED if HTOP_UNSUPPORTED
myhtopplatsources = unsupported/Platform.c \ myhtopplatsources = unsupported/Platform.c \
unsupported/UnsupportedProcess.c unsupported/UnsupportedProcessList.c \ unsupported/UnsupportedProcess.c unsupported/UnsupportedProcessList.c \
@ -184,8 +182,17 @@ endif
# ---- # ----
htop_SOURCES = $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources) SUFFIXES = .h
nodist_htop_SOURCES = config.h
BUILT_SOURCES = $(myhtopheaders) $(myhtopplatheaders)
htop_SOURCES = $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources) config.h
.PHONY: htop-headers clean-htop-headers
htop-headers: $(myhtopheaders) $(all_platform_headers)
clean-htop-headers:
-rm -f $(myhtopheaders) $(all_platform_headers)
target: target:
echo $(htop_SOURCES) echo $(htop_SOURCES)
@ -196,9 +203,15 @@ profile:
debug: debug:
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DDEBUG" $(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DDEBUG"
symbols:
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DNDEBUG"
coverage: coverage:
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-fprofile-arcs -ftest-coverage -DDEBUG" LDFLAGS="-lgcov" $(MAKE) all CFLAGS="" AM_CPPFLAGS="-fprofile-arcs -ftest-coverage -DDEBUG" LDFLAGS="-lgcov"
.c.h:
@srcdir@/scripts/MakeHeader.py $<
cppcheck: cppcheck:
cppcheck -q -v . --enable=all -DHAVE_CGROUP -DHAVE_OPENVZ -DHAVE_TASKSTATS cppcheck -q -v . --enable=all -DHAVE_CGROUP -DHAVE_OPENVZ -DHAVE_TASKSTATS

View File

@ -16,6 +16,9 @@ in the source distribution for its full text.
#include <sys/param.h> #include <sys/param.h>
#include <assert.h> #include <assert.h>
/*{
#include "Meter.h"
}*/
int MemoryMeter_attributes[] = { int MemoryMeter_attributes[] = {
MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MemoryMeter #ifndef HEADER_MemoryMeter
#define HEADER_MemoryMeter #define HEADER_MemoryMeter
/* /*

101
Meter.c
View File

@ -11,6 +11,7 @@ in the source distribution for its full text.
#include "Object.h" #include "Object.h"
#include "CRT.h" #include "CRT.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "ListItem.h"
#include "Settings.h" #include "Settings.h"
#include <math.h> #include <math.h>
@ -18,11 +19,108 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <assert.h> #include <assert.h>
#include <sys/time.h>
#define METER_BUFFER_LEN 256
#define GRAPH_DELAY (DEFAULT_DELAY/2) #define GRAPH_DELAY (DEFAULT_DELAY/2)
#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */ #define GRAPH_HEIGHT 4 /* Unit: rows (lines) */
/*{
#include "ListItem.h"
#include <sys/time.h>
typedef struct Meter_ Meter;
typedef void(*Meter_Init)(Meter*);
typedef void(*Meter_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int);
typedef void(*Meter_UpdateValues)(Meter*, char*, int);
typedef void(*Meter_Draw)(Meter*, int, int, int);
typedef struct MeterClass_ {
ObjectClass super;
const Meter_Init init;
const Meter_Done done;
const Meter_UpdateMode updateMode;
const Meter_Draw draw;
const Meter_UpdateValues updateValues;
const int defaultMode;
const double total;
const int* attributes;
const char* name;
const char* uiName;
const char* caption;
const char* description;
const char maxItems;
char curItems;
} MeterClass;
#define As_Meter(this_) ((MeterClass*)((this_)->super.klass))
#define Meter_initFn(this_) As_Meter(this_)->init
#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_))
#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_))
#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode
#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_)
#define Meter_drawFn(this_) As_Meter(this_)->draw
#define Meter_doneFn(this_) As_Meter(this_)->done
#define Meter_updateValues(this_, buf_, sz_) \
As_Meter(this_)->updateValues((Meter*)(this_), buf_, sz_)
#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode
#define Meter_getItems(this_) As_Meter(this_)->curItems
#define Meter_setItems(this_, n_) As_Meter(this_)->curItems = (n_)
#define Meter_attributes(this_) As_Meter(this_)->attributes
#define Meter_name(this_) As_Meter(this_)->name
#define Meter_uiName(this_) As_Meter(this_)->uiName
struct Meter_ {
Object super;
Meter_Draw draw;
char* caption;
int mode;
int param;
void* drawData;
int h;
struct ProcessList_* pl;
double* values;
double total;
};
typedef struct MeterMode_ {
Meter_Draw draw;
const char* uiName;
int h;
} MeterMode;
typedef enum {
CUSTOM_METERMODE = 0,
BAR_METERMODE,
TEXT_METERMODE,
GRAPH_METERMODE,
LED_METERMODE,
LAST_METERMODE
} MeterModeId;
typedef struct GraphData_ {
struct timeval time;
double values[METER_BUFFER_LEN];
} GraphData;
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
#endif
MeterClass Meter_class = { MeterClass Meter_class = {
.super = { .super = {
.extends = Class(Object) .extends = Class(Object)
@ -425,9 +523,6 @@ MeterMode* Meter_modes[] = {
static void BlankMeter_updateValues(Meter* this, char* buffer, int size) { static void BlankMeter_updateValues(Meter* this, char* buffer, int size) {
(void) this; (void) buffer; (void) size; (void) this; (void) buffer; (void) size;
if (size > 0) {
*buffer = 0;
}
} }
static void BlankMeter_display(Object* cast, RichString* out) { static void BlankMeter_display(Object* cast, RichString* out) {

45
Meter.h
View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Meter #ifndef HEADER_Meter
#define HEADER_Meter #define HEADER_Meter
/* /*
@ -7,11 +9,16 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "ListItem.h"
#include <sys/time.h>
#define METER_BUFFER_LEN 256 #define METER_BUFFER_LEN 256
#define GRAPH_DELAY (DEFAULT_DELAY/2)
#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */
#include "ListItem.h"
#include <sys/time.h>
typedef struct Meter_ Meter; typedef struct Meter_ Meter;
typedef void(*Meter_Init)(Meter*); typedef void(*Meter_Init)(Meter*);
@ -89,6 +96,17 @@ typedef struct GraphData_ {
double values[METER_BUFFER_LEN]; double values[METER_BUFFER_LEN];
} GraphData; } GraphData;
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
#endif
extern MeterClass Meter_class; extern MeterClass Meter_class;
Meter* Meter_new(struct ProcessList_* pl, int param, MeterClass* type); Meter* Meter_new(struct ProcessList_* pl, int param, MeterClass* type);
@ -103,8 +121,29 @@ void Meter_setMode(Meter* this, int modeIndex);
ListItem* Meter_toListItem(Meter* this, bool moving); ListItem* Meter_toListItem(Meter* this, bool moving);
/* ---------- TextMeterMode ---------- */
/* ---------- BarMeterMode ---------- */
/* ---------- GraphMeterMode ---------- */
#ifdef HAVE_LIBNCURSESW
#define PIXPERROW_UTF8 4
#endif
#define PIXPERROW_ASCII 2
/* ---------- LEDMeterMode ---------- */
#ifdef HAVE_LIBNCURSESW
#endif
extern MeterMode* Meter_modes[]; extern MeterMode* Meter_modes[];
/* Blank meter */
extern int BlankMeter_attributes[]; extern int BlankMeter_attributes[];
extern MeterClass BlankMeter_class; extern MeterClass BlankMeter_class;

View File

@ -11,6 +11,25 @@ in the source distribution for its full text.
#include <assert.h> #include <assert.h>
#include "CRT.h" #include "CRT.h"
/*{
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
typedef struct MetersPanel_ MetersPanel;
struct MetersPanel_ {
Panel super;
Settings* settings;
Vector* meters;
ScreenManager* scr;
MetersPanel* leftNeighbor;
MetersPanel* rightNeighbor;
bool moving;
};
}*/
// Note: In code the meters are known to have bar/text/graph "Modes", but in UI // Note: In code the meters are known to have bar/text/graph "Modes", but in UI
// we call them "Styles". // we call them "Styles".

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MetersPanel #ifndef HEADER_MetersPanel
#define HEADER_MetersPanel #define HEADER_MetersPanel
/* /*
@ -24,6 +26,14 @@ struct MetersPanel_ {
bool moving; bool moving;
}; };
// Note: In code the meters are known to have bar/text/graph "Modes", but in UI
// we call them "Styles".
// We avoid UTF-8 arrows ← → here as they might display full-width on Chinese
// terminals, breaking our aligning.
// In <http://unicode.org/reports/tr11/>, arrows (U+2019..U+2199) are
// considered "Ambiguous characters".
void MetersPanel_setMoving(MetersPanel* this, bool moving); void MetersPanel_setMoving(MetersPanel* this, bool moving);
extern PanelClass MetersPanel_class; extern PanelClass MetersPanel_class;

1
NEWS
View File

@ -2,3 +2,4 @@
See the commit history for news of the past. See the commit history for news of the past.
See the bug tracker for news of the future. See the bug tracker for news of the future.
Run the program for news of the present. Run the program for news of the present.

View File

@ -1,13 +1,47 @@
/* /*
htop - Object.c htop - Object.c
(C) 2004-2012 Hisham H. Muhammad (C) 2004-2012 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Object.h" #include "Object.h"
/*{
#include "RichString.h"
#include "XAlloc.h"
typedef struct Object_ Object;
typedef void(*Object_Display)(Object*, RichString*);
typedef long(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*);
#define Object_getClass(obj_) ((Object*)(obj_))->klass
#define Object_setClass(obj_, class_) Object_getClass(obj_) = (ObjectClass*) class_
#define Object_delete(obj_) Object_getClass(obj_)->delete((Object*)(obj_))
#define Object_displayFn(obj_) Object_getClass(obj_)->display
#define Object_display(obj_, str_) Object_getClass(obj_)->display((Object*)(obj_), str_)
#define Object_compare(obj_, other_) Object_getClass(obj_)->compare((const void*)(obj_), other_)
#define Class(class_) ((ObjectClass*)(&(class_ ## _class)))
#define AllocThis(class_) (class_*) xMalloc(sizeof(class_)); Object_setClass(this, Class(class_));
typedef struct ObjectClass_ {
const void* extends;
const Object_Display display;
const Object_Delete delete;
const Object_Compare compare;
} ObjectClass;
struct Object_ {
ObjectClass* klass;
};
}*/
ObjectClass Object_class = { ObjectClass Object_class = {
.extends = NULL .extends = NULL
}; };

View File

@ -1,16 +1,16 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Object #ifndef HEADER_Object
#define HEADER_Object #define HEADER_Object
/* /*
htop - Object.h htop - Object.h
(C) 2004-2012 Hisham H. Muhammad (C) 2004-2012 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "RichString.h" #include "RichString.h"
#include "XAlloc.h" #include "XAlloc.h"
#include "Macros.h"
typedef struct Object_ Object; typedef struct Object_ Object;
@ -41,10 +41,6 @@ struct Object_ {
ObjectClass* klass; ObjectClass* klass;
}; };
typedef union {
int i;
void* v;
} Arg;
extern ObjectClass Object_class; extern ObjectClass Object_class;

View File

@ -23,6 +23,30 @@ in the source distribution for its full text.
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
/*{
#include "InfoScreen.h"
typedef struct OpenFiles_Data_ {
char* data[256];
} OpenFiles_Data;
typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ {
InfoScreen super;
pid_t pid;
} OpenFilesScreen;
}*/
InfoScreenClass OpenFilesScreen_class = { InfoScreenClass OpenFilesScreen_class = {
.super = { .super = {
@ -100,7 +124,6 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
item->data[cmd] = xStrdup(line + 1); item->data[cmd] = xStrdup(line + 1);
free(line); free(line);
} }
fclose(fd);
int wstatus; int wstatus;
if (waitpid(child, &wstatus, 0) == -1) { if (waitpid(child, &wstatus, 0) == -1) {
pdata->error = 1; pdata->error = 1;

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_OpenFilesScreen #ifndef HEADER_OpenFilesScreen
#define HEADER_OpenFilesScreen #define HEADER_OpenFilesScreen
/* /*
@ -29,6 +31,7 @@ typedef struct OpenFilesScreen_ {
pid_t pid; pid_t pid;
} OpenFilesScreen; } OpenFilesScreen;
extern InfoScreenClass OpenFilesScreen_class; extern InfoScreenClass OpenFilesScreen_class;
OpenFilesScreen* OpenFilesScreen_new(Process* process); OpenFilesScreen* OpenFilesScreen_new(Process* process);

120
Panel.c
View File

@ -19,6 +19,83 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
//#link curses
/*{
#include "Object.h"
#include "Vector.h"
#include "FunctionBar.h"
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
HANDLED = 0x01,
IGNORED = 0x02,
BREAK_LOOP = 0x04,
REDRAW = 0x08,
RESCAN = 0x10,
SYNTH_KEY = 0x20,
} HandlerResult;
#define EVENT_SET_SELECTED -1
#define EVENT_HEADER_CLICK(x_) (-10000 + x_)
#define EVENT_HEADER_CLICK_GET_X(ev_) (ev_ + 10000)
#define EVENT_IS_HEADER_CLICK(ev_) (ev_ >= -10000 && ev_ < -9000)
#define EVENT_SCREEN_TAB_CLICK(x_) (-20000 + x_)
#define EVENT_SCREEN_TAB_GET_X(ev_) (ev_ + 20000)
#define EVENT_IS_SCREEN_TAB_CLICK(ev_) (ev_ >= -20000 && ev_ < -10000)
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
typedef struct PanelClass_ {
const ObjectClass super;
const Panel_EventHandler eventHandler;
} PanelClass;
#define As_Panel(this_) ((PanelClass*)((this_)->super.klass))
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
#define Panel_eventHandler(this_, ev_) As_Panel(this_)->eventHandler((Panel*)(this_), ev_)
struct Panel_ {
Object super;
int x, y, w, h;
int cursorX, cursorY;
WINDOW* window;
Vector* items;
int selected;
int oldSelected;
int selectedLen;
void* eventHandlerState;
int scrollV;
short scrollH;
bool needsRedraw;
bool cursorOn;
FunctionBar* currentBar;
FunctionBar* defaultBar;
RichString header;
int selectionColor;
};
#define Panel_setDefaultBar(this_) do{ (this_)->currentBar = (this_)->defaultBar; }while(0)
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#define KEY_CTRL(l) ((l)-'A'+1)
void Panel_setCursorToSelection(Panel* this) {
this->cursorY = this->y + this->selected - this->scrollV + 1;
this->cursorX = this->x + this->selectedLen - this->scrollH;
}
PanelClass Panel_class = { PanelClass Panel_class = {
.super = { .super = {
.extends = Class(Object), .extends = Class(Object),
@ -46,6 +123,8 @@ void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool
this->y = y; this->y = y;
this->w = w; this->w = w;
this->h = h; this->h = h;
this->cursorX = 0;
this->cursorY = 0;
this->eventHandlerState = NULL; this->eventHandlerState = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE); this->items = Vector_new(type, owner, DEFAULT_SIZE);
this->scrollV = 0; this->scrollV = 0;
@ -198,14 +277,6 @@ void Panel_setSelected(Panel* this, int selected) {
} }
} }
void Panel_splice(Panel *this, Vector* from) {
assert (this != NULL);
assert (from != NULL);
Vector_splice(this->items, from);
this->needsRedraw = true;
}
void Panel_draw(Panel* this, bool focus) { void Panel_draw(Panel* this, bool focus) {
assert (this != NULL); assert (this != NULL);
@ -224,7 +295,7 @@ void Panel_draw(Panel* this, bool focus) {
mvhline(y, x, ' ', this->w); mvhline(y, x, ' ', this->w);
if (scrollH < headerLen) { if (scrollH < headerLen) {
RichString_printoffnVal(this->header, y, x, scrollH, RichString_printoffnVal(this->header, y, x, scrollH,
MINIMUM(headerLen - scrollH, this->w)); MIN(headerLen - scrollH, this->w));
} }
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
y++; y++;
@ -235,7 +306,7 @@ void Panel_draw(Panel* this, bool focus) {
this->scrollV = 0; this->scrollV = 0;
this->needsRedraw = true; this->needsRedraw = true;
} else if (this->scrollV >= size) { } else if (this->scrollV >= size) {
this->scrollV = MAXIMUM(size - 1, 0); this->scrollV = MAX(size - 1, 0);
this->needsRedraw = true; this->needsRedraw = true;
} }
// ensure selection is on screen // ensure selection is on screen
@ -248,7 +319,7 @@ void Panel_draw(Panel* this, bool focus) {
} }
int first = this->scrollV; int first = this->scrollV;
int upTo = MINIMUM(first + h, size); int upTo = MIN(first + h, size);
int selectionColor = focus int selectionColor = focus
? this->selectionColor ? this->selectionColor
@ -262,7 +333,7 @@ void Panel_draw(Panel* this, bool focus) {
RichString_begin(item); RichString_begin(item);
Object_display(itemObj, &item); Object_display(itemObj, &item);
int itemLen = RichString_sizeVal(item); int itemLen = RichString_sizeVal(item);
int amt = MINIMUM(itemLen - scrollH, this->w); int amt = MIN(itemLen - scrollH, this->w);
bool selected = (i == this->selected); bool selected = (i == this->selected);
if (selected) { if (selected) {
attrset(selectionColor); attrset(selectionColor);
@ -297,19 +368,18 @@ void Panel_draw(Panel* this, bool focus) {
mvhline(y+ this->oldSelected - first, x+0, ' ', this->w); mvhline(y+ this->oldSelected - first, x+0, ' ', this->w);
if (scrollH < oldLen) if (scrollH < oldLen)
RichString_printoffnVal(old, y+this->oldSelected - first, x, RichString_printoffnVal(old, y+this->oldSelected - first, x,
scrollH, MINIMUM(oldLen - scrollH, this->w)); scrollH, MIN(oldLen - scrollH, this->w));
attrset(selectionColor); attrset(selectionColor);
mvhline(y+this->selected - first, x+0, ' ', this->w); mvhline(y+this->selected - first, x+0, ' ', this->w);
RichString_setAttr(&new, selectionColor); RichString_setAttr(&new, selectionColor);
if (scrollH < newLen) if (scrollH < newLen)
RichString_printoffnVal(new, y+this->selected - first, x, RichString_printoffnVal(new, y+this->selected - first, x,
scrollH, MINIMUM(newLen - scrollH, this->w)); scrollH, MIN(newLen - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]); attrset(CRT_colors[RESET_COLOR]);
RichString_end(new); RichString_end(new);
RichString_end(old); RichString_end(old);
} }
this->oldSelected = this->selected; this->oldSelected = this->selected;
move(0, 0);
} }
bool Panel_onKey(Panel* this, int key) { bool Panel_onKey(Panel* this, int key) {
@ -338,7 +408,7 @@ bool Panel_onKey(Panel* this, int key) {
case KEY_LEFT: case KEY_LEFT:
case KEY_CTRL('B'): case KEY_CTRL('B'):
if (this->scrollH > 0) { if (this->scrollH > 0) {
this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0); this->scrollH -= MAX(CRT_scrollHAmount, 0);
this->needsRedraw = true; this->needsRedraw = true;
} }
break; break;
@ -349,12 +419,12 @@ bool Panel_onKey(Panel* this, int key) {
break; break;
case KEY_PPAGE: case KEY_PPAGE:
this->selected -= (this->h - 1); this->selected -= (this->h - 1);
this->scrollV = MAXIMUM(0, this->scrollV - this->h + 1); this->scrollV = MAX(0, this->scrollV - this->h + 1);
this->needsRedraw = true; this->needsRedraw = true;
break; break;
case KEY_NPAGE: case KEY_NPAGE:
this->selected += (this->h - 1); this->selected += (this->h - 1);
this->scrollV = MAXIMUM(0, MINIMUM(Vector_size(this->items) - this->h, this->scrollV = MAX(0, MIN(Vector_size(this->items) - this->h,
this->scrollV + this->h - 1)); this->scrollV + this->h - 1));
this->needsRedraw = true; this->needsRedraw = true;
break; break;
@ -386,7 +456,7 @@ bool Panel_onKey(Panel* this, int key) {
break; break;
case KEY_CTRL('E'): case KEY_CTRL('E'):
case '$': case '$':
this->scrollH = MAXIMUM(this->selectedLen - this->w, 0); this->scrollH = MAX(this->selectedLen - this->w, 0);
this->needsRedraw = true; this->needsRedraw = true;
break; break;
default: default:
@ -441,3 +511,15 @@ HandlerResult Panel_selectByTyping(Panel* this, int ch) {
} }
return IGNORED; return IGNORED;
} }
int Panel_getCh(Panel* this) {
if (this->cursorOn) {
move(this->cursorY, this->cursorX);
curs_set(1);
} else {
curs_set(0);
}
set_escdelay(25);
return getch();
}

29
Panel.h
View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Panel #ifndef HEADER_Panel
#define HEADER_Panel #define HEADER_Panel
/* /*
@ -7,6 +9,8 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
//#link curses
#include "Object.h" #include "Object.h"
#include "Vector.h" #include "Vector.h"
#include "FunctionBar.h" #include "FunctionBar.h"
@ -25,8 +29,12 @@ typedef enum HandlerResult_ {
#define EVENT_SET_SELECTED -1 #define EVENT_SET_SELECTED -1
#define EVENT_HEADER_CLICK(x_) (-10000 + x_) #define EVENT_HEADER_CLICK(x_) (-10000 + x_)
#define EVENT_IS_HEADER_CLICK(ev_) (ev_ >= -10000 && ev_ <= -9000)
#define EVENT_HEADER_CLICK_GET_X(ev_) (ev_ + 10000) #define EVENT_HEADER_CLICK_GET_X(ev_) (ev_ + 10000)
#define EVENT_IS_HEADER_CLICK(ev_) (ev_ >= -10000 && ev_ < -9000)
#define EVENT_SCREEN_TAB_CLICK(x_) (-20000 + x_)
#define EVENT_SCREEN_TAB_GET_X(ev_) (ev_ + 20000)
#define EVENT_IS_SCREEN_TAB_CLICK(ev_) (ev_ >= -20000 && ev_ < -10000)
typedef HandlerResult(*Panel_EventHandler)(Panel*, int); typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
@ -42,6 +50,7 @@ typedef struct PanelClass_ {
struct Panel_ { struct Panel_ {
Object super; Object super;
int x, y, w, h; int x, y, w, h;
int cursorX, cursorY;
WINDOW* window; WINDOW* window;
Vector* items; Vector* items;
int selected; int selected;
@ -51,6 +60,7 @@ struct Panel_ {
int scrollV; int scrollV;
short scrollH; short scrollH;
bool needsRedraw; bool needsRedraw;
bool cursorOn;
FunctionBar* currentBar; FunctionBar* currentBar;
FunctionBar* defaultBar; FunctionBar* defaultBar;
RichString header; RichString header;
@ -59,8 +69,18 @@ struct Panel_ {
#define Panel_setDefaultBar(this_) do{ (this_)->currentBar = (this_)->defaultBar; }while(0) #define Panel_setDefaultBar(this_) do{ (this_)->currentBar = (this_)->defaultBar; }while(0)
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#define KEY_CTRL(l) ((l)-'A'+1) #define KEY_CTRL(l) ((l)-'A'+1)
void Panel_setCursorToSelection(Panel* this);
extern PanelClass Panel_class; extern PanelClass Panel_class;
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type, FunctionBar* fuBar); Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type, FunctionBar* fuBar);
@ -75,7 +95,7 @@ void Panel_setSelectionColor(Panel* this, int color);
RichString* Panel_getHeader(Panel* this); RichString* Panel_getHeader(Panel* this);
void Panel_setHeader(Panel* this, const char* header); extern void Panel_setHeader(Panel* this, const char* header);
void Panel_move(Panel* this, int x, int y); void Panel_move(Panel* this, int x, int y);
@ -107,10 +127,11 @@ void Panel_setSelected(Panel* this, int selected);
void Panel_draw(Panel* this, bool focus); void Panel_draw(Panel* this, bool focus);
void Panel_splice(Panel *this, Vector* from);
bool Panel_onKey(Panel* this, int key); bool Panel_onKey(Panel* this, int key);
HandlerResult Panel_selectByTyping(Panel* this, int ch); HandlerResult Panel_selectByTyping(Panel* this, int ch);
int Panel_getCh(Panel* this);
#endif #endif

266
Process.c
View File

@ -1,7 +1,6 @@
/* /*
htop - Process.c htop - Process.c
(C) 2004-2015 Hisham H. Muhammad (C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
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.
*/ */
@ -9,8 +8,6 @@ in the source distribution for its full text.
#include "Process.h" #include "Process.h"
#include "Settings.h" #include "Settings.h"
#include "config.h"
#include "CRT.h" #include "CRT.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "RichString.h" #include "RichString.h"
@ -21,6 +18,7 @@ in the source distribution for its full text.
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
@ -32,12 +30,173 @@ in the source distribution for its full text.
#include <math.h> #include <math.h>
#ifdef MAJOR_IN_MKDEV #ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h> #include <sys/mkdev.h>
#elif defined(MAJOR_IN_SYSMACROS) #elif defined(MAJOR_IN_SYSMACROS) || \
(defined(HAVE_SYS_SYSMACROS_H) && HAVE_SYS_SYSMACROS_H)
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#endif #endif
#ifdef __ANDROID__
#define SYS_ioprio_get __NR_ioprio_get
#define SYS_ioprio_set __NR_ioprio_set
#endif
// On Linux, this works only with glibc 2.1+. On earlier versions
// the behavior is similar to have a hardcoded page size.
#ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
/*{
#include "Object.h"
#include <sys/types.h>
#include <inttypes.h>
#define PROCESS_FLAG_IO 0x0001
typedef enum ProcessFields {
NULL_PROCESSFIELD = 0,
PID = 1,
COMM = 2,
STATE = 3,
PPID = 4,
PGRP = 5,
SESSION = 6,
TTY_NR = 7,
TPGID = 8,
MINFLT = 10,
MAJFLT = 12,
PRIORITY = 18,
NICE = 19,
STARTTIME = 21,
PROCESSOR = 38,
M_SIZE = 39,
M_RESIDENT = 40,
ST_UID = 46,
PERCENT_CPU = 47,
PERCENT_MEM = 48,
USER = 49,
TIME = 50,
NLWP = 51,
TGID = 52,
} ProcessField;
typedef struct ProcessPidColumn_ {
int id;
char* label;
} ProcessPidColumn;
typedef struct Process_ {
Object super;
struct Settings_* settings;
unsigned long long int time;
pid_t pid;
pid_t ppid;
pid_t tgid;
char* comm;
int commLen;
int indent;
int basenameOffset;
bool updated;
char state;
bool tag;
bool showChildren;
bool show;
unsigned int pgrp;
unsigned int session;
unsigned int tty_nr;
int tpgid;
uid_t st_uid;
unsigned long int flags;
int processor;
float percent_cpu;
float percent_mem;
char* user;
long int priority;
long int nice;
long int nlwp;
char starttime_show[8];
time_t starttime_ctime;
long m_size;
long m_resident;
int exit_signal;
unsigned long int minflt;
unsigned long int majflt;
#ifdef DEBUG
long int itrealvalue;
unsigned long int vsize;
long int rss;
unsigned long int rlim;
unsigned long int startcode;
unsigned long int endcode;
unsigned long int startstack;
unsigned long int kstkesp;
unsigned long int kstkeip;
unsigned long int signal;
unsigned long int blocked;
unsigned long int sigignore;
unsigned long int sigcatch;
unsigned long int wchan;
unsigned long int nswap;
unsigned long int cnswap;
#endif
} Process;
typedef struct ProcessFieldData_ {
const char* name;
const char* title;
const char* description;
uint64_t flags;
} ProcessFieldData;
// Implemented in platform-specific code:
void Process_writeField(Process* this, RichString* str, ProcessField field);
long Process_compare(const void* v1, const void* v2);
void Process_delete(Object* cast);
bool Process_isThread(Process* this);
extern ProcessFieldData Process_fields[];
extern ProcessPidColumn Process_pidColumns[];
extern char Process_pidFormat[20];
typedef Process*(*Process_New)(struct Settings_*);
typedef void (*Process_WriteField)(Process*, RichString*, ProcessField);
typedef struct ProcessClass_ {
const ObjectClass super;
const Process_WriteField writeField;
} ProcessClass;
#define As_Process(this_) ((ProcessClass*)((this_)->super.klass))
#define Process_getParentPid(process_) (process_->tgid == process_->pid ? process_->ppid : process_->tgid)
#define Process_isChildOf(process_, pid_) (process_->tgid == pid_ || (process_->tgid == process_->pid && process_->ppid == pid_))
#define Process_sortState(state) ((state) == 'I' ? 0x100 : (state))
}*/
static int Process_getuid = -1; static int Process_getuid = -1;
#define ONE_K 1024L
#define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K)
#define ONE_DECIMAL_K 1000L
#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K)
#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K)
char Process_pidFormat[20] = "%7d "; char Process_pidFormat[20] = "%7d ";
static char Process_titleBuffer[20][20]; static char Process_titleBuffer[20][20];
@ -70,7 +229,7 @@ void Process_humanNumber(RichString* str, unsigned long number, bool coloring) {
if(number >= (10 * ONE_DECIMAL_M)) { if(number >= (10 * ONE_DECIMAL_M)) {
#ifdef __LP64__ #ifdef __LP64__
if(number >= (100 * ONE_DECIMAL_G)) { if(number >= (100 * ONE_DECIMAL_G)) {
len = snprintf(buffer, 10, "%4luT ", number / ONE_G); len = snprintf(buffer, 10, "%4ldT ", number / ONE_G);
RichString_appendn(str, largeNumberColor, buffer, len); RichString_appendn(str, largeNumberColor, buffer, len);
return; return;
} else if (number >= (1000 * ONE_DECIMAL_M)) { } else if (number >= (1000 * ONE_DECIMAL_M)) {
@ -80,7 +239,7 @@ void Process_humanNumber(RichString* str, unsigned long number, bool coloring) {
} }
#endif #endif
if(number >= (100 * ONE_DECIMAL_M)) { if(number >= (100 * ONE_DECIMAL_M)) {
len = snprintf(buffer, 10, "%4luG ", number / ONE_M); len = snprintf(buffer, 10, "%4ldG ", number / ONE_M);
RichString_appendn(str, largeNumberColor, buffer, len); RichString_appendn(str, largeNumberColor, buffer, len);
return; return;
} }
@ -88,11 +247,11 @@ void Process_humanNumber(RichString* str, unsigned long number, bool coloring) {
RichString_appendn(str, largeNumberColor, buffer, len); RichString_appendn(str, largeNumberColor, buffer, len);
return; return;
} else if (number >= 100000) { } else if (number >= 100000) {
len = snprintf(buffer, 10, "%4luM ", number / ONE_K); len = snprintf(buffer, 10, "%4ldM ", number / ONE_K);
RichString_appendn(str, processMegabytesColor, buffer, len); RichString_appendn(str, processMegabytesColor, buffer, len);
return; return;
} else if (number >= 1000) { } else if (number >= 1000) {
len = snprintf(buffer, 10, "%2lu", number/1000); len = snprintf(buffer, 10, "%2ld", number/1000);
RichString_appendn(str, processMegabytesColor, buffer, len); RichString_appendn(str, processMegabytesColor, buffer, len);
number %= 1000; number %= 1000;
len = snprintf(buffer, 10, "%03lu ", number); len = snprintf(buffer, 10, "%03lu ", number);
@ -119,15 +278,8 @@ void Process_colorNumber(RichString* str, unsigned long long number, bool colori
if ((long long) number == -1LL) { if ((long long) number == -1LL) {
int len = snprintf(buffer, 13, " no perm "); int len = snprintf(buffer, 13, " no perm ");
RichString_appendn(str, CRT_colors[PROCESS_SHADOW], buffer, len); RichString_appendn(str, CRT_colors[PROCESS_SHADOW], buffer, len);
} else if (number >= 100000LL * ONE_DECIMAL_T) { } else if (number > 10000000000) {
xSnprintf(buffer, 13, "%11llu ", number / ONE_DECIMAL_G); xSnprintf(buffer, 13, "%11lld ", number / 1000);
RichString_appendn(str, largeNumberColor, buffer, 12);
} else if (number >= 100LL * ONE_DECIMAL_T) {
xSnprintf(buffer, 13, "%11llu ", number / ONE_DECIMAL_M);
RichString_appendn(str, largeNumberColor, buffer, 8);
RichString_appendn(str, processMegabytesColor, buffer+8, 4);
} else if (number >= 10LL * ONE_DECIMAL_G) {
xSnprintf(buffer, 13, "%11llu ", number / ONE_DECIMAL_K);
RichString_appendn(str, largeNumberColor, buffer, 5); RichString_appendn(str, largeNumberColor, buffer, 5);
RichString_appendn(str, processMegabytesColor, buffer+5, 3); RichString_appendn(str, processMegabytesColor, buffer+5, 3);
RichString_appendn(str, processColor, buffer+8, 4); RichString_appendn(str, processColor, buffer+8, 4);
@ -207,21 +359,33 @@ void Process_outputRate(RichString* str, char* buffer, int n, double rate, int c
} else if (rate < ONE_K) { } else if (rate < ONE_K) {
int len = snprintf(buffer, n, "%7.2f B/s ", rate); int len = snprintf(buffer, n, "%7.2f B/s ", rate);
RichString_appendn(str, processColor, buffer, len); RichString_appendn(str, processColor, buffer, len);
} else if (rate < ONE_M) { } else if (rate < ONE_K * ONE_K) {
int len = snprintf(buffer, n, "%7.2f K/s ", rate / ONE_K); int len = snprintf(buffer, n, "%7.2f K/s ", rate / ONE_K);
RichString_appendn(str, processColor, buffer, len); RichString_appendn(str, processColor, buffer, len);
} else if (rate < ONE_G) { } else if (rate < ONE_K * ONE_K * ONE_K) {
int len = snprintf(buffer, n, "%7.2f M/s ", rate / ONE_M); int len = snprintf(buffer, n, "%7.2f M/s ", rate / ONE_K / ONE_K);
RichString_appendn(str, processMegabytesColor, buffer, len); RichString_appendn(str, processMegabytesColor, buffer, len);
} else if (rate < ONE_T) {
int len = snprintf(buffer, n, "%7.2f G/s ", rate / ONE_G);
RichString_appendn(str, largeNumberColor, buffer, len);
} else { } else {
int len = snprintf(buffer, n, "%7.2f T/s ", rate / ONE_T); int len = snprintf(buffer, n, "%7.2f G/s ", rate / ONE_K / ONE_K / ONE_K);
RichString_appendn(str, largeNumberColor, buffer, len); RichString_appendn(str, largeNumberColor, buffer, len);
} }
} }
void Process_printPercentage(float val, char* buffer, int n, int* attr) {
if (val >= 0) {
if (val < 100) {
xSnprintf(buffer, n, "%4.1f ", val);
} else if (val < 1000) {
xSnprintf(buffer, n, "%3d. ", (unsigned int)val);
} else {
xSnprintf(buffer, n, "%4d ", (unsigned int)val);
}
} else {
*attr = CRT_colors[PROCESS_SHADOW];
xSnprintf(buffer, n, " N/A ");
}
}
void Process_writeField(Process* this, RichString* str, ProcessField field) { void Process_writeField(Process* this, RichString* str, ProcessField field) {
char buffer[256]; buffer[255] = '\0'; char buffer[256]; buffer[255] = '\0';
int attr = CRT_colors[DEFAULT_COLOR]; int attr = CRT_colors[DEFAULT_COLOR];
@ -230,30 +394,15 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
bool coloring = this->settings->highlightMegabytes; bool coloring = this->settings->highlightMegabytes;
switch (field) { switch (field) {
case PERCENT_CPU: { case PERCENT_CPU: Process_printPercentage(this->percent_cpu, buffer, n, &attr); break;
if (this->percent_cpu > 999.9) { case PERCENT_MEM: Process_printPercentage(this->percent_mem, buffer, n, &attr); break;
xSnprintf(buffer, n, "%4u ", (unsigned int)this->percent_cpu);
} else if (this->percent_cpu > 99.9) {
xSnprintf(buffer, n, "%3u. ", (unsigned int)this->percent_cpu);
} else {
xSnprintf(buffer, n, "%4.1f ", this->percent_cpu);
}
break;
}
case PERCENT_MEM: {
if (this->percent_mem > 99.9) {
xSnprintf(buffer, n, "100. ");
} else {
xSnprintf(buffer, n, "%4.1f ", this->percent_mem);
}
break;
}
case COMM: { case COMM: {
if (this->settings->highlightThreads && Process_isThread(this)) { if (this->settings->highlightThreads && Process_isThread(this)) {
attr = CRT_colors[PROCESS_THREAD]; attr = CRT_colors[PROCESS_THREAD];
baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
} }
if (!this->settings->treeView || this->indent == 0) { ScreenSettings* ss = this->settings->ss;
if (!ss->treeView || this->indent == 0) {
Process_writeCommand(this, attr, baseattr, str); Process_writeCommand(this, attr, baseattr, str);
return; return;
} else { } else {
@ -266,20 +415,15 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
if (indent & (1U << i)) if (indent & (1U << i))
maxIndent = i+1; maxIndent = i+1;
for (int i = 0; i < maxIndent - 1; i++) { for (int i = 0; i < maxIndent - 1; i++) {
int written, ret; int written;
if (indent & (1 << i)) if (indent & (1 << i))
ret = snprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]); written = snprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]);
else else
ret = snprintf(buf, n, " "); written = snprintf(buf, n, " ");
if (ret < 0 || ret >= n) {
written = n;
} else {
written = ret;
}
buf += written; buf += written;
n -= written; n -= written;
} }
const char* draw = CRT_treeStr[lastItem ? (this->settings->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE]; const char* draw = CRT_treeStr[lastItem ? (ss->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE];
xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] );
RichString_append(str, CRT_colors[PROCESS_TREE], buffer); RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
Process_writeCommand(this, attr, baseattr, str); Process_writeCommand(this, attr, baseattr, str);
@ -323,7 +467,7 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
} }
break; break;
} }
case ST_UID: xSnprintf(buffer, n, "%5d ", this->st_uid); break; case ST_UID: xSnprintf(buffer, n, "%4d ", this->st_uid); break;
case TIME: Process_printTime(str, this->time); return; case TIME: Process_printTime(str, this->time); return;
case TGID: xSnprintf(buffer, n, Process_pidFormat, this->tgid); break; case TGID: xSnprintf(buffer, n, Process_pidFormat, this->tgid); break;
case TPGID: xSnprintf(buffer, n, Process_pidFormat, this->tpgid); break; case TPGID: xSnprintf(buffer, n, Process_pidFormat, this->tpgid); break;
@ -350,7 +494,7 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
void Process_display(Object* cast, RichString* out) { void Process_display(Object* cast, RichString* out) {
Process* this = (Process*) cast; Process* this = (Process*) cast;
ProcessField* fields = this->settings->fields; ProcessField* fields = this->settings->ss->fields;
RichString_prune(out); RichString_prune(out);
for (int i = 0; fields[i]; i++) for (int i = 0; fields[i]; i++)
As_Process(this)->writeField(this, out, fields[i]); As_Process(this)->writeField(this, out, fields[i]);
@ -401,15 +545,14 @@ bool Process_setPriority(Process* this, int priority) {
return (err == 0); return (err == 0);
} }
bool Process_changePriorityBy(Process* this, Arg delta) { bool Process_changePriorityBy(Process* this, int delta) {
return Process_setPriority(this, this->nice + delta.i); return Process_setPriority(this, this->nice + delta);
} }
bool Process_sendSignal(Process* this, Arg sgn) { void Process_sendSignal(Process* this, int sgn) {
CRT_dropPrivileges(); CRT_dropPrivileges();
bool ok = (kill(this->pid, sgn.i) == 0); kill(this->pid, (int) sgn);
CRT_restorePrivileges(); CRT_restorePrivileges();
return ok;
} }
long Process_pidCompare(const void* v1, const void* v2) { long Process_pidCompare(const void* v1, const void* v2) {
@ -421,14 +564,15 @@ long Process_pidCompare(const void* v1, const void* v2) {
long Process_compare(const void* v1, const void* v2) { long Process_compare(const void* v1, const void* v2) {
Process *p1, *p2; Process *p1, *p2;
Settings *settings = ((Process*)v1)->settings; Settings *settings = ((Process*)v1)->settings;
if (settings->direction == 1) { ScreenSettings* ss = settings->ss;
if (ss->direction == 1) {
p1 = (Process*)v1; p1 = (Process*)v1;
p2 = (Process*)v2; p2 = (Process*)v2;
} else { } else {
p2 = (Process*)v1; p2 = (Process*)v1;
p1 = (Process*)v2; p1 = (Process*)v2;
} }
switch (settings->sortKey) { switch (ss->sortKey) {
case PERCENT_CPU: case PERCENT_CPU:
return (p2->percent_cpu > p1->percent_cpu ? 1 : -1); return (p2->percent_cpu > p1->percent_cpu ? 1 : -1);
case PERCENT_MEM: case PERCENT_MEM:

View File

@ -1,13 +1,19 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Process #ifndef HEADER_Process
#define HEADER_Process #define HEADER_Process
/* /*
htop - Process.h htop - Process.h
(C) 2004-2015 Hisham H. Muhammad (C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifdef MAJOR_IN_MKDEV
#elif defined(MAJOR_IN_SYSMACROS) || \
(defined(HAVE_SYS_SYSMACROS_H) && HAVE_SYS_SYSMACROS_H)
#endif
#ifdef __ANDROID__ #ifdef __ANDROID__
#define SYS_ioprio_get __NR_ioprio_get #define SYS_ioprio_get __NR_ioprio_get
#define SYS_ioprio_set __NR_ioprio_set #define SYS_ioprio_set __NR_ioprio_set
@ -23,6 +29,7 @@ in the source distribution for its full text.
#include "Object.h" #include "Object.h"
#include <sys/types.h> #include <sys/types.h>
#include <inttypes.h>
#define PROCESS_FLAG_IO 0x0001 #define PROCESS_FLAG_IO 0x0001
@ -55,7 +62,7 @@ typedef enum ProcessFields {
typedef struct ProcessPidColumn_ { typedef struct ProcessPidColumn_ {
int id; int id;
const char* label; char* label;
} ProcessPidColumn; } ProcessPidColumn;
typedef struct Process_ { typedef struct Process_ {
@ -128,7 +135,7 @@ typedef struct ProcessFieldData_ {
const char* name; const char* name;
const char* title; const char* title;
const char* description; const char* description;
int flags; uint64_t flags;
} ProcessFieldData; } ProcessFieldData;
// Implemented in platform-specific code: // Implemented in platform-specific code:
@ -160,12 +167,10 @@ typedef struct ProcessClass_ {
#define ONE_K 1024L #define ONE_K 1024L
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K) #define ONE_G (ONE_M * ONE_K)
#define ONE_T ((long long)ONE_G * ONE_K)
#define ONE_DECIMAL_K 1000L #define ONE_DECIMAL_K 1000L
#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) #define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K)
#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) #define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K)
#define ONE_DECIMAL_T ((long long)ONE_DECIMAL_G * ONE_DECIMAL_K)
extern char Process_pidFormat[20]; extern char Process_pidFormat[20];
@ -179,6 +184,8 @@ void Process_printTime(RichString* str, unsigned long long totalHundredths);
void Process_outputRate(RichString* str, char* buffer, int n, double rate, int coloring); void Process_outputRate(RichString* str, char* buffer, int n, double rate, int coloring);
void Process_printPercentage(float val, char* buffer, int n, int* attr);
void Process_writeField(Process* this, RichString* str, ProcessField field); void Process_writeField(Process* this, RichString* str, ProcessField field);
void Process_display(Object* cast, RichString* out); void Process_display(Object* cast, RichString* out);
@ -193,9 +200,9 @@ void Process_toggleTag(Process* this);
bool Process_setPriority(Process* this, int priority); bool Process_setPriority(Process* this, int priority);
bool Process_changePriorityBy(Process* this, Arg delta); bool Process_changePriorityBy(Process* this, int delta);
bool Process_sendSignal(Process* this, Arg sgn); void Process_sendSignal(Process* this, int sgn);
long Process_pidCompare(const void* v1, const void* v2); long Process_pidCompare(const void* v1, const void* v2);

View File

@ -14,12 +14,75 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/*{
#include "Vector.h"
#include "Hashtable.h"
#include "UsersTable.h"
#include "Panel.h"
#include "Process.h"
#include "Settings.h"
ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { #ifdef HAVE_LIBHWLOC
#include <hwloc.h>
#endif
#ifndef MAX_NAME
#define MAX_NAME 128
#endif
#ifndef MAX_READ
#define MAX_READ 2048
#endif
typedef struct ProcessList_ {
Settings* settings;
Vector* processes;
Vector* processes2;
Hashtable* processTable;
UsersTable* usersTable;
Panel* panel;
int following;
uid_t userId;
const char* incFilter;
Hashtable* pidWhiteList;
#ifdef HAVE_LIBHWLOC
hwloc_topology_t topology;
bool topologyOk;
#endif
int totalTasks;
int runningTasks;
int userlandThreads;
int kernelThreads;
unsigned long long int totalMem;
unsigned long long int usedMem;
unsigned long long int freeMem;
unsigned long long int sharedMem;
unsigned long long int buffersMem;
unsigned long long int cachedMem;
unsigned long long int totalSwap;
unsigned long long int usedSwap;
unsigned long long int freeSwap;
int cpuCount;
} ProcessList;
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
void ProcessList_delete(ProcessList* pl);
void ProcessList_goThroughEntries(ProcessList* pl);
}*/
ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) {
this->processes = Vector_new(klass, true, DEFAULT_SIZE); this->processes = Vector_new(klass, true, DEFAULT_SIZE);
this->processTable = Hashtable_new(140, false); this->processTable = Hashtable_new(140, false);
this->usersTable = usersTable; this->usersTable = usersTable;
this->pidMatchList = pidMatchList; this->pidWhiteList = pidWhiteList;
this->userId = userId; this->userId = userId;
// tree-view auxiliary buffer // tree-view auxiliary buffer
@ -30,19 +93,12 @@ ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable*
#ifdef HAVE_LIBHWLOC #ifdef HAVE_LIBHWLOC
this->topologyOk = false; this->topologyOk = false;
if (hwloc_topology_init(&this->topology) == 0) { int topoErr = hwloc_topology_init(&this->topology);
this->topologyOk = if (topoErr == 0) {
#if HWLOC_API_VERSION < 0x00020000 topoErr = hwloc_topology_load(this->topology);
/* try to ignore the top-level machine object type */ }
0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_MACHINE) && if (topoErr == 0) {
/* ignore caches, which don't add structure */ this->topologyOk = true;
0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CORE) &&
0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CACHE) &&
0 == hwloc_topology_set_flags(this->topology, HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) &&
#else
0 == hwloc_topology_set_all_types_filter(this->topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE) &&
#endif
0 == hwloc_topology_load(this->topology);
} }
#endif #endif
@ -68,14 +124,15 @@ void ProcessList_setPanel(ProcessList* this, Panel* panel) {
void ProcessList_printHeader(ProcessList* this, RichString* header) { void ProcessList_printHeader(ProcessList* this, RichString* header) {
RichString_prune(header); RichString_prune(header);
ProcessField* fields = this->settings->fields; ProcessField* fields = this->settings->ss->fields;
for (int i = 0; fields[i]; i++) { for (int i = 0; fields[i]; i++) {
const char* field = Process_fields[fields[i]].title; unsigned int key = fields[i];
const char* field = Process_fields[key].title;
if (!field) field = "- "; if (!field) field = "- ";
if (!this->settings->treeView && this->settings->sortKey == fields[i]) int color = (!this->settings->ss->treeView && this->settings->ss->sortKey == key)
RichString_append(header, CRT_colors[PANEL_SELECTION_FOCUS], field); ? CRT_colors[PANEL_SELECTION_FOCUS]
else : CRT_colors[PANEL_HEADER_FOCUS];
RichString_append(header, CRT_colors[PANEL_HEADER_FOCUS], field); RichString_append(header, color, field);
} }
} }
@ -144,19 +201,19 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
} }
void ProcessList_sort(ProcessList* this) { void ProcessList_sort(ProcessList* this) {
if (!this->settings->treeView) { if (!this->settings->ss->treeView) {
Vector_insertionSort(this->processes); Vector_insertionSort(this->processes);
} else { } else {
// Save settings // Save settings
int direction = this->settings->direction; int direction = this->settings->ss->direction;
int sortKey = this->settings->sortKey; int sortKey = this->settings->ss->sortKey;
// Sort by PID // Sort by PID
this->settings->sortKey = PID; this->settings->ss->sortKey = PID;
this->settings->direction = 1; this->settings->ss->direction = 1;
Vector_quickSort(this->processes); Vector_quickSort(this->processes);
// Restore settings // Restore settings
this->settings->sortKey = sortKey; this->settings->ss->sortKey = sortKey;
this->settings->direction = direction; this->settings->ss->direction = direction;
int vsize = Vector_size(this->processes); int vsize = Vector_size(this->processes);
// Find all processes whose parent is not visible // Find all processes whose parent is not visible
int size; int size;
@ -215,7 +272,7 @@ void ProcessList_sort(ProcessList* this) {
ProcessField ProcessList_keyAt(ProcessList* this, int at) { ProcessField ProcessList_keyAt(ProcessList* this, int at) {
int x = 0; int x = 0;
ProcessField* fields = this->settings->fields; ProcessField* fields = this->settings->ss->fields;
ProcessField field; ProcessField field;
for (int i = 0; (field = fields[i]); i++) { for (int i = 0; (field = fields[i]); i++) {
const char* title = Process_fields[field].title; const char* title = Process_fields[field].title;
@ -254,7 +311,7 @@ void ProcessList_rebuildPanel(ProcessList* this) {
if ( (!p->show) if ( (!p->show)
|| (this->userId != (uid_t) -1 && (p->st_uid != this->userId)) || (this->userId != (uid_t) -1 && (p->st_uid != this->userId))
|| (incFilter && !(String_contains_i(p->comm, incFilter))) || (incFilter && !(String_contains_i(p->comm, incFilter)))
|| (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) ) || (this->pidWhiteList && !Hashtable_get(this->pidWhiteList, p->tgid)) )
hidden = true; hidden = true;
if (!hidden) { if (!hidden) {

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ProcessList #ifndef HEADER_ProcessList
#define HEADER_ProcessList #define HEADER_ProcessList
/* /*
@ -38,7 +40,7 @@ typedef struct ProcessList_ {
int following; int following;
uid_t userId; uid_t userId;
const char* incFilter; const char* incFilter;
Hashtable* pidMatchList; Hashtable* pidWhiteList;
#ifdef HAVE_LIBHWLOC #ifdef HAVE_LIBHWLOC
hwloc_topology_t topology; hwloc_topology_t topology;
@ -64,12 +66,12 @@ typedef struct ProcessList_ {
} ProcessList; } ProcessList;
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidMatchList, uid_t userId); ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
void ProcessList_delete(ProcessList* pl); void ProcessList_delete(ProcessList* pl);
void ProcessList_goThroughEntries(ProcessList* pl); void ProcessList_goThroughEntries(ProcessList* pl);
ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId);
void ProcessList_done(ProcessList* this); void ProcessList_done(ProcessList* this);

57
README
View File

@ -1,37 +1,52 @@
# [![htop](htop.png)](https://htop.dev) [![Build Status](https://travis-ci.org/hishamhm/htop.svg?branch=master)](https://travis-ci.org/hishamhm/htop)
[![PayPal donate](https://img.shields.io/badge/paypal-donate-green.svg)](http://hisham.hm/htop/index.php?page=donate)
[![CI](https://github.com/htop-dev/htop/workflows/CI/badge.svg)](https://github.com/htop-dev/htop/actions) [htop](http://hisham.hm/htop/)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/21665/badge.svg)](https://scan.coverity.com/projects/21665) ====
[![Mailing List](https://img.shields.io/badge/Mailing%20List-htop-blue.svg)](https://groups.io/g/htop)
[![IRC #htop](https://img.shields.io/badge/IRC-htop-blue.svg)](https://webchat.freenode.net/#htop)
[![Github Release](https://img.shields.io/github/release/htop-dev/htop.svg)](https://github.com/htop-dev/htop/releases/latest)
[![Download](https://api.bintray.com/packages/htop/source/htop/images/download.svg)](https://bintray.com/htop/source/htop/_latestVersion)
## Introduction by Hisham Muhammad <hisham@gobolinux.org> (2004 - 2016)
`htop` is a cross-platform interactive process viewer. Introduction
It requires `ncurses`. ------------
For more information and details on how to contribute to `htop` This is `htop`, an interactive process viewer.
visit [htop.dev](https://htop.dev). It requires `ncurses`. It is developed primarily on Linux,
but we also have code for running under FreeBSD and Mac OS X
(help and testing are wanted for these platforms!)
## Build instructions This software has evolved considerably over the years,
and is reasonably complete, but there is always room for improvement.
Comparison between `htop` and classic `top`
-------------------------------------------
* In `htop` you can scroll the list vertically and horizontally
to see all processes and full command lines.
* In `top` you are subject to a delay for each unassigned
key you press (especially annoying when multi-key escape
sequences are triggered by accident).
* `htop` starts faster (`top` seems to collect data for a while
before displaying anything).
* In `htop` you don't need to type the process number to
kill a process, in `top` you do.
* In `htop` you don't need to type the process number or
the priority value to renice a process, in `top` you do.
* In `htop` you can kill multiple processes at once.
* `top` is older, hence, more tested.
Compilation instructions
------------------------
This program is distributed as a standard autotools-based package. This program is distributed as a standard autotools-based package.
For detailed instructions see the `INSTALL` file, which See the [INSTALL](/INSTALL) file for detailed instructions.
is created after `./autogen.sh` is run.
When compiling from a [release tarball](https://github.com/htop-dev/htop/releases/), run: When compiling from a [release tarball](https://hisham.hm/htop/releases/), run:
~~~ shell
./configure && make ./configure && make
~~~
For compiling sources downloaded from the Git repository, run: For compiling sources downloaded from the Git repository, run:
~~~ shell
./autogen.sh && ./configure && make ./autogen.sh && ./configure && make
~~~
By default `make install` will install into `/usr/local`, for changing By default `make install` will install into `/usr/local`, for changing
the path use `./configure --prefix=/some/path`. the path use `./configure --prefix=/some/path`.
@ -39,6 +54,8 @@ the path use `./configure --prefix=/some/path`.
See the manual page (`man htop`) or the on-line help ('F1' or 'h' See the manual page (`man htop`) or the on-line help ('F1' or 'h'
inside `htop`) for a list of supported key commands. inside `htop`) for a list of supported key commands.
If not all keys work check your curses configuration.
## License ## License
GNU General Public License, version 2 (GPL-2.0) GNU General Public License, version 2 (GPL-2.0)

View File

@ -7,11 +7,66 @@ in the source distribution for its full text.
#include "RichString.h" #include "RichString.h"
#include "XAlloc.h" #include "XAlloc.h"
#include "Macros.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define RICHSTRING_MAXLEN 350
/*{
#include "config.h"
#include <ctype.h>
#include <assert.h>
#ifdef HAVE_NCURSESW_CURSES_H
#include <ncursesw/curses.h>
#elif HAVE_NCURSES_NCURSES_H
#include <ncurses/ncurses.h>
#elif HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#elif HAVE_NCURSES_H
#include <ncurses.h>
#elif HAVE_CURSES_H
#include <curses.h>
#endif
#ifdef HAVE_LIBNCURSESW
#include <wctype.h>
#endif
#define RichString_size(this) ((this)->chlen)
#define RichString_sizeVal(this) ((this).chlen)
#define RichString_begin(this) RichString (this); memset(&this, 0, sizeof(RichString)); (this).chptr = (this).chstr;
#define RichString_beginAllocated(this) memset(&this, 0, sizeof(RichString)); (this).chptr = (this).chstr;
#define RichString_end(this) RichString_prune(&(this));
#ifdef HAVE_LIBNCURSESW
#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr)
#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255)
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = (CharType) { .chars = { ch, 0 } }; } while(0)
#define CharType cchar_t
#else
#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr)
#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n)
#define RichString_getCharVal(this, i) ((this).chptr[i])
#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
#define CharType chtype
#endif
typedef struct RichString_ {
int chlen;
CharType* chptr;
CharType chstr[RICHSTRING_MAXLEN+1];
} RichString;
}*/
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
#endif
#define charBytes(n) (sizeof(CharType) * (n)) #define charBytes(n) (sizeof(CharType) * (n))
static void RichString_extendLen(RichString* this, int len) { static void RichString_extendLen(RichString* this, int len) {

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_RichString #ifndef HEADER_RichString
#define HEADER_RichString #define HEADER_RichString
/* /*
@ -7,6 +9,7 @@ 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 RICHSTRING_MAXLEN 350
#include "config.h" #include "config.h"
#include <ctype.h> #include <ctype.h>
@ -49,17 +52,24 @@ in the source distribution for its full text.
#define CharType chtype #define CharType chtype
#endif #endif
#define RICHSTRING_MAXLEN 350
typedef struct RichString_ { typedef struct RichString_ {
int chlen; int chlen;
CharType* chptr; CharType* chptr;
CharType chstr[RICHSTRING_MAXLEN+1]; CharType chstr[RICHSTRING_MAXLEN+1];
} RichString; } RichString;
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
#endif
#define charBytes(n) (sizeof(CharType) * (n))
#define RichString_setLen(this, len) do{ if(len < RICHSTRING_MAXLEN && this->chlen < RICHSTRING_MAXLEN) { RichString_setChar(this,len,0); this->chlen=len; } else RichString_extendLen(this,len); }while(0)
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
void RichString_setAttrn(RichString* this, int attrs, int start, int finish); extern void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
int RichString_findChar(RichString* this, char c, int start); int RichString_findChar(RichString* this, char c, int start);

View File

@ -13,9 +13,38 @@ in the source distribution for its full text.
#include <assert.h> #include <assert.h>
#include <time.h> #include <time.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
/*{
#include "FunctionBar.h"
#include "Vector.h"
#include "Header.h"
#include "Settings.h"
#include "Panel.h"
typedef enum Orientation_ {
VERTICAL,
HORIZONTAL
} Orientation;
typedef struct ScreenManager_ {
int x1;
int y1;
int x2;
int y2;
Orientation orientation;
Vector* panels;
const char* name;
int panelCount;
const Header* header;
const Settings* settings;
bool owner;
bool allowFocusChange;
} ScreenManager;
}*/
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, const Settings* settings, bool owner) { ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, const Settings* settings, bool owner) {
ScreenManager* this; ScreenManager* this;
@ -44,30 +73,46 @@ inline int ScreenManager_size(ScreenManager* this) {
} }
void ScreenManager_add(ScreenManager* this, Panel* item, int size) { void ScreenManager_add(ScreenManager* this, Panel* item, int size) {
ScreenManager_insert(this, item, size, Vector_size(this->panels));
}
void ScreenManager_insert(ScreenManager* this, Panel* item, int size, int idx) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
int lastX = 0; int lastX = 0;
if (this->panelCount > 0) { if (idx > 0) {
Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1); Panel* last = (Panel*) Vector_get(this->panels, idx - 1);
lastX = last->x + last->w + 1; lastX = last->x + last->w + 1;
} }
int height = LINES - this->y1 + this->y2; int height = LINES - this->y1 + this->y2;
if (size > 0) { if (size <= 0) {
Panel_resize(item, size, height); size = COLS-this->x1+this->x2-lastX;
} else {
Panel_resize(item, COLS-this->x1+this->x2-lastX, height);
} }
Panel_resize(item, size, height);
Panel_move(item, lastX, this->y1); Panel_move(item, lastX, this->y1);
if (idx < this->panelCount) {
for (int i = idx + 1; i <= this->panelCount; i++) {
Panel* p = (Panel*) Vector_get(this->panels, i);
Panel_move(p, p->x + size, p->y);
}
}
} }
// TODO: VERTICAL // TODO: VERTICAL
Vector_add(this->panels, item); Vector_insert(this->panels, idx, item);
item->needsRedraw = true; item->needsRedraw = true;
this->panelCount++; this->panelCount++;
} }
Panel* ScreenManager_remove(ScreenManager* this, int idx) { Panel* ScreenManager_remove(ScreenManager* this, int idx) {
assert(this->panelCount > idx); assert(this->panelCount > idx);
int w = ((Panel*) Vector_get(this->panels, idx))->w;
Panel* panel = (Panel*) Vector_remove(this->panels, idx); Panel* panel = (Panel*) Vector_remove(this->panels, idx);
this->panelCount--; this->panelCount--;
if (idx < this->panelCount) {
for (int i = idx; i < this->panelCount; i++) {
Panel* p = (Panel*) Vector_get(this->panels, i);
Panel_move(p, p->x - w, p->y);
}
}
return panel; return panel;
} }
@ -104,7 +149,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
if (*rescan) { if (*rescan) {
*oldTime = newTime; *oldTime = newTime;
ProcessList_scan(pl); ProcessList_scan(pl);
if (*sortTimeout == 0 || this->settings->treeView) { if (*sortTimeout == 0 || this->settings->ss->treeView) {
ProcessList_sort(pl); ProcessList_sort(pl);
*sortTimeout = 1; *sortTimeout = 1;
} }
@ -117,27 +162,73 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
*rescan = false; *rescan = false;
} }
static inline bool drawTab(int* y, int* x, int l, const char* name, bool cur) {
attrset(CRT_colors[cur ? SCREENS_CUR_BORDER : SCREENS_OTH_BORDER]);
mvaddch(*y, *x, '[');
(*x)++;
if (*x >= l) return false;
int nameLen = strlen(name);
int n = MIN(l - *x, nameLen);
attrset(CRT_colors[cur ? SCREENS_CUR_TEXT : SCREENS_OTH_TEXT]);
mvaddnstr(*y, *x, name, n);
*x += n;
if (*x >= l) return false;
attrset(CRT_colors[cur ? SCREENS_CUR_BORDER : SCREENS_OTH_BORDER]);
mvaddch(*y, *x, ']');
*x += 2;
if (*x >= l) return false;
return true;
}
static void ScreenManager_drawScreenTabs(ScreenManager* this) {
ScreenSettings** screens = this->settings->screens;
int cur = this->settings->ssIndex;
int l = COLS;
Panel* panel = (Panel*) Vector_get(this->panels, 0);
int y = panel->y - 1;
int x = 2;
if (this->name) {
drawTab(&y, &x, l, this->name, true);
return;
}
for (int s = 0; screens[s]; s++) {
bool ok = drawTab(&y, &x, l, screens[s]->name, s == cur);
if (!ok) {
break;
}
}
attrset(CRT_colors[RESET_COLOR]);
}
static void ScreenManager_drawPanels(ScreenManager* this, int focus) { static void ScreenManager_drawPanels(ScreenManager* this, int focus) {
const int nPanels = this->panelCount; if (this->settings->screenTabs) {
ScreenManager_drawScreenTabs(this);
}
int nPanels = this->panelCount;
for (int i = 0; i < nPanels; i++) { for (int i = 0; i < nPanels; i++) {
Panel* panel = (Panel*) Vector_get(this->panels, i); Panel* panel = (Panel*) Vector_get(this->panels, i);
Panel_draw(panel, i == focus); Panel_draw(panel, i == focus);
if (i < nPanels) {
if (this->orientation == HORIZONTAL) { if (this->orientation == HORIZONTAL) {
mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1); mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
} }
} }
} }
}
static Panel* setCurrentPanel(Panel* panel) { static Panel* setCurrentPanel(ScreenManager* this, int focus) {
Panel* panel = (Panel*) Vector_get(this->panels, focus);
FunctionBar_draw(panel->currentBar, NULL); FunctionBar_draw(panel->currentBar, NULL);
return panel; return panel;
} }
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) { void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, char* name) {
bool quit = false; bool quit = false;
int focus = 0; int focus = 0;
Panel* panelFocus = setCurrentPanel((Panel*) Vector_get(this->panels, focus)); Panel* panelFocus = setCurrentPanel(this, focus);
double oldTime = 0.0; double oldTime = 0.0;
@ -150,6 +241,8 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
int sortTimeout = 0; int sortTimeout = 0;
int resetSortTimeout = 5; int resetSortTimeout = 5;
this->name = name;
while (!quit) { while (!quit) {
if (this->header) { if (this->header) {
checkRecalculation(this, &oldTime, &sortTimeout, &redraw, &rescan, &timedOut); checkRecalculation(this, &oldTime, &sortTimeout, &redraw, &rescan, &timedOut);
@ -160,11 +253,10 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
} }
int prevCh = ch; int prevCh = ch;
set_escdelay(25); ch = Panel_getCh(panelFocus);
ch = getch();
HandlerResult result = IGNORED; HandlerResult result = IGNORED;
if (ch == KEY_MOUSE && this->settings->enableMouse) { if (ch == KEY_MOUSE) {
ch = ERR; ch = ERR;
MEVENT mevent; MEVENT mevent;
int ok = getmouse(&mevent); int ok = getmouse(&mevent);
@ -179,11 +271,14 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
if (mevent.y == panel->y) { if (mevent.y == panel->y) {
ch = EVENT_HEADER_CLICK(mevent.x - panel->x); ch = EVENT_HEADER_CLICK(mevent.x - panel->x);
break; break;
} else if (this->settings->screenTabs && mevent.y == panel->y - 1) {
ch = EVENT_SCREEN_TAB_CLICK(mevent.x);
break;
} else if (mevent.y > panel->y && mevent.y <= panel->y+panel->h) { } else if (mevent.y > panel->y && mevent.y <= panel->y+panel->h) {
ch = KEY_MOUSE; ch = KEY_MOUSE;
if (panel == panelFocus || this->allowFocusChange) { if (panel == panelFocus || this->allowFocusChange) {
focus = i; focus = i;
panelFocus = setCurrentPanel(panel); panelFocus = setCurrentPanel(this, i);
Object* oldSelection = Panel_getSelected(panel); Object* oldSelection = Panel_getSelected(panel);
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
if (Panel_getSelected(panel) == oldSelection) { if (Panel_getSelected(panel) == oldSelection) {
@ -259,7 +354,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
tryLeft: tryLeft:
if (focus > 0) if (focus > 0)
focus--; focus--;
panelFocus = setCurrentPanel((Panel*) Vector_get(this->panels, focus)); panelFocus = setCurrentPanel(this, focus);
if (Panel_size(panelFocus) == 0 && focus > 0) if (Panel_size(panelFocus) == 0 && focus > 0)
goto tryLeft; goto tryLeft;
break; break;
@ -274,7 +369,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
tryRight: tryRight:
if (focus < this->panelCount - 1) if (focus < this->panelCount - 1)
focus++; focus++;
panelFocus = setCurrentPanel((Panel*) Vector_get(this->panels, focus)); panelFocus = setCurrentPanel(this, focus);
if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1) if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
goto tryRight; goto tryRight;
break; break;

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ScreenManager #ifndef HEADER_ScreenManager
#define HEADER_ScreenManager #define HEADER_ScreenManager
/* /*
@ -7,6 +9,7 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "FunctionBar.h"
#include "Vector.h" #include "Vector.h"
#include "Header.h" #include "Header.h"
#include "Settings.h" #include "Settings.h"
@ -24,6 +27,7 @@ typedef struct ScreenManager_ {
int y2; int y2;
Orientation orientation; Orientation orientation;
Vector* panels; Vector* panels;
const char* name;
int panelCount; int panelCount;
const Header* header; const Header* header;
const Settings* settings; const Settings* settings;
@ -31,18 +35,21 @@ typedef struct ScreenManager_ {
bool allowFocusChange; bool allowFocusChange;
} ScreenManager; } ScreenManager;
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, const Settings* settings, bool owner); ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, const Settings* settings, bool owner);
void ScreenManager_delete(ScreenManager* this); void ScreenManager_delete(ScreenManager* this);
int ScreenManager_size(ScreenManager* this); extern int ScreenManager_size(ScreenManager* this);
void ScreenManager_add(ScreenManager* this, Panel* item, int size); void ScreenManager_add(ScreenManager* this, Panel* item, int size);
void ScreenManager_insert(ScreenManager* this, Panel* item, int size, int idx);
Panel* ScreenManager_remove(ScreenManager* this, int idx); Panel* ScreenManager_remove(ScreenManager* this, int idx);
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, Panel** lastFocus, int* lastKey); void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, char* name);
#endif #endif

331
ScreensPanel.c Normal file
View File

@ -0,0 +1,331 @@
/*
htop - ScreensPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "ScreensPanel.h"
#include "Platform.h"
#include "StringUtils.h"
#include "CRT.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/*{
#include "Panel.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Settings.h"
#include "ListItem.h"
#ifndef SCREEN_NAME_LEN
#define SCREEN_NAME_LEN 20
#endif
typedef struct ScreensPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
ColumnsPanel* columns;
char buffer[SCREEN_NAME_LEN + 1];
char* saved;
int cursor;
bool moving;
bool renaming;
} ScreensPanel;
typedef struct ScreenListItem_ {
ListItem super;
ScreenSettings* ss;
} ScreenListItem;
}*/
ObjectClass ScreenListItem_class = {
.extends = Class(ListItem),
.display = ListItem_display,
.delete = ListItem_delete,
.compare = ListItem_compare
};
ScreenListItem* ScreenListItem_new(const char* value, ScreenSettings* ss) {
ScreenListItem* this = AllocThis(ScreenListItem);
ListItem_init((ListItem*)this, value, 0);
this->ss = ss;
return this;
}
static const char* const ScreensFunctions[] = {" ", "Rename", " ", " ", "New ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
static void ScreensPanel_delete(Object* object) {
Panel* super = (Panel*) object;
ScreensPanel* this = (ScreensPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult ScreensPanel_eventHandlerRenaming(Panel* super, int ch) {
ScreensPanel* const this = (ScreensPanel*) super;
//ListItem* item = (ListItem*)Panel_getSelected(super);
if (ch >= 32 && ch < 127 && ch != 61 && ch != 22) {
if (this->cursor < SCREEN_NAME_LEN - 1) {
this->buffer[this->cursor] = ch;
this->cursor++;
super->selectedLen = strlen(this->buffer);
Panel_setCursorToSelection(super);
}
} else {
switch(ch) {
case 127:
case KEY_BACKSPACE:
{
if (this->cursor > 0) {
this->cursor--;
this->buffer[this->cursor] = '\0';
super->selectedLen = strlen(this->buffer);
Panel_setCursorToSelection(super);
}
break;
}
case 0x0a:
case 0x0d:
case KEY_ENTER:
{
ListItem* item = (ListItem*) Panel_getSelected(super);
free(this->saved);
item->value = xStrdup(this->buffer);
this->renaming = false;
super->cursorOn = false;
Panel_setSelectionColor(super, CRT_colors[PANEL_SELECTION_FOCUS]);
ScreensPanel_update(super);
break;
}
case 27: // Esc
{
ListItem* item = (ListItem*) Panel_getSelected(super);
item->value = this->saved;
this->renaming = false;
super->cursorOn = false;
Panel_setSelectionColor(super, CRT_colors[PANEL_SELECTION_FOCUS]);
break;
}
}
}
return HANDLED;
}
static void startRenaming(Panel* super) {
ScreensPanel* const this = (ScreensPanel*) super;
ListItem* item = (ListItem*) Panel_getSelected(super);
this->renaming = true;
super->cursorOn = true;
char* name = item->value;
this->saved = name;
strncpy(this->buffer, name, SCREEN_NAME_LEN);
this->buffer[SCREEN_NAME_LEN] = '\0';
this->cursor = strlen(this->buffer);
item->value = this->buffer;
Panel_setSelectionColor(super, CRT_colors[PANEL_EDIT]);
super->selectedLen = strlen(this->buffer);
Panel_setCursorToSelection(super);
}
static void rebuildSettingsArray(Panel* super) {
ScreensPanel* const this = (ScreensPanel*) super;
int n = Panel_size(super);
free(this->settings->screens);
this->settings->screens = xMalloc(sizeof(ScreenSettings*) * (n + 1));
this->settings->screens[n] = NULL;
for (int i = 0; i < n; i++) {
ScreenListItem* item = (ScreenListItem*) Panel_get(super, i);
this->settings->screens[i] = item->ss;
}
this->settings->nScreens = n;
}
static void addNewScreen(Panel* super) {
ScreensPanel* const this = (ScreensPanel*) super;
char* name = "New";
ScreenSettings* ss = Settings_newScreen(this->settings, name, "PID Command");
ScreenListItem* item = ScreenListItem_new(name, ss);
int idx = Panel_getSelectedIndex(super);
Panel_insert(super, idx + 1, (Object*) item);
Panel_setSelected(super, idx + 1);
}
static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) {
ScreensPanel* const this = (ScreensPanel*) super;
int selected = Panel_getSelectedIndex(super);
ScreenListItem* oldFocus = (ScreenListItem*) Panel_getSelected(super);
bool shouldRebuildArray = false;
HandlerResult result = IGNORED;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case KEY_RECLICK:
{
this->moving = !(this->moving);
Panel_setSelectionColor(super, this->moving ? CRT_colors[PANEL_SELECTION_FOLLOW] : CRT_colors[PANEL_SELECTION_FOCUS]);
((ListItem*)Panel_getSelected(super))->moving = this->moving;
result = HANDLED;
break;
}
case EVENT_SET_SELECTED:
result = HANDLED;
break;
case KEY_NPAGE:
case KEY_PPAGE:
case KEY_HOME:
case KEY_END: {
Panel_onKey(super, ch);
break;
}
case KEY_F(2):
case KEY_CTRL('R'):
{
startRenaming(super);
result = HANDLED;
break;
}
case KEY_F(5):
case KEY_CTRL('N'):
{
addNewScreen(super);
startRenaming(super);
shouldRebuildArray = true;
result = HANDLED;
break;
}
case KEY_UP:
{
if (!this->moving) {
Panel_onKey(super, ch);
break;
}
/* else fallthrough */
}
case KEY_F(7):
case '[':
case '-':
{
Panel_moveSelectedUp(super);
shouldRebuildArray = true;
result = HANDLED;
break;
}
case KEY_DOWN:
{
if (!this->moving) {
Panel_onKey(super, ch);
break;
}
/* else fallthrough */
}
case KEY_F(8):
case ']':
case '+':
{
Panel_moveSelectedDown(super);
shouldRebuildArray = true;
result = HANDLED;
break;
}
case KEY_F(9):
//case KEY_DC:
{
if (Panel_size(super) > 1) {
Panel_remove(super, selected);
}
shouldRebuildArray = true;
result = HANDLED;
break;
}
default:
{
if (ch < 255 && isalpha(ch))
result = Panel_selectByTyping(super, ch);
if (result == BREAK_LOOP)
result = IGNORED;
break;
}
}
ScreenListItem* newFocus = (ScreenListItem*) Panel_getSelected(super);
if (oldFocus != newFocus) {
ColumnsPanel_fill(this->columns, newFocus->ss);
result = HANDLED;
}
if (shouldRebuildArray) {
rebuildSettingsArray(super);
}
if (result == HANDLED)
ScreensPanel_update(super);
return result;
}
static HandlerResult ScreensPanel_eventHandler(Panel* super, int ch) {
ScreensPanel* const this = (ScreensPanel*) super;
if (this->renaming) {
return ScreensPanel_eventHandlerRenaming(super, ch);
} else {
return ScreensPanel_eventHandlerNormal(super, ch);
}
}
PanelClass ScreensPanel_class = {
.super = {
.extends = Class(Panel),
.delete = ScreensPanel_delete
},
.eventHandler = ScreensPanel_eventHandler
};
ScreensPanel* ScreensPanel_new(Settings* settings) {
ScreensPanel* this = AllocThis(ScreensPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(ScreensFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
this->settings = settings;
this->columns = ColumnsPanel_new(settings->screens[0], &(settings->changed));
this->moving = false;
this->renaming = false;
super->cursorOn = false;
this->cursor = 0;
Panel_setHeader(super, "Screens");
for (unsigned int i = 0; i < settings->nScreens; i++) {
ScreenSettings* ss = settings->screens[i];
char* name = ss->name;
Panel_add(super, (Object*) ScreenListItem_new(name, ss));
}
return this;
}
void ScreensPanel_update(Panel* super) {
ScreensPanel* this = (ScreensPanel*) super;
int size = Panel_size(super);
this->settings->changed = true;
this->settings->screens = xRealloc(this->settings->screens, sizeof(char*) * (size+1));
for (int i = 0; i < size; i++) {
ScreenListItem* item = (ScreenListItem*) Panel_get(super, i);
ScreenSettings* ss = item->ss;
free(ss->name);
this->settings->screens[i] = ss;
ss->name = xStrdup(((ListItem*) item)->value);
}
this->settings->screens[size] = NULL;
}

51
ScreensPanel.h Normal file
View File

@ -0,0 +1,51 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ScreensPanel
#define HEADER_ScreensPanel
/*
htop - ScreensPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Settings.h"
#include "ListItem.h"
#ifndef SCREEN_NAME_LEN
#define SCREEN_NAME_LEN 20
#endif
typedef struct ScreensPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
ColumnsPanel* columns;
char buffer[SCREEN_NAME_LEN + 1];
char* saved;
int cursor;
bool moving;
bool renaming;
} ScreensPanel;
typedef struct ScreenListItem_ {
ListItem super;
ScreenSettings* ss;
} ScreenListItem;
extern ObjectClass ScreenListItem_class;
ScreenListItem* ScreenListItem_new(const char* value, ScreenSettings* ss);
extern PanelClass ScreensPanel_class;
ScreensPanel* ScreensPanel_new(Settings* settings);
void ScreensPanel_update(Panel* super);
#endif

View File

@ -17,25 +17,149 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#define DEFAULT_DELAY 15
/*{
#include "Process.h"
#include <stdbool.h>
typedef struct {
const char* name;
const char* columns;
const char* sortKey;
} ScreenDefaults;
typedef struct {
int len;
char** names;
int* modes;
} MeterColumnSettings;
typedef struct {
char* name;
ProcessField* fields;
int flags;
int direction;
ProcessField sortKey;
bool treeView;
} ScreenSettings;
typedef struct Settings_ {
char* filename;
MeterColumnSettings meterColumns[2];
ScreenSettings** screens;
unsigned int nScreens;
unsigned int ssIndex;
ScreenSettings* ss;
int colorScheme;
int delay;
int cpuCount;
bool countCPUsFromZero;
bool detailedCPUTime;
bool showProgramPath;
bool hideThreads;
bool shadowOtherUsers;
bool showThreadNames;
bool hideKernelThreads;
bool hideUserlandThreads;
bool highlightBaseName;
bool highlightMegabytes;
bool highlightThreads;
bool updateProcessNames;
bool accountGuestInCPUMeter;
bool headerMargin;
bool screenTabs;
bool changed;
} Settings;
#ifndef Settings_cpuId
#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1)
#endif
}*/
static void writeList(FILE* fd, char** list, int len) {
const char* sep = "";
for (int i = 0; i < len; i++) {
fprintf(fd, "%s%s", sep, list[i]);
sep = " ";
}
fprintf(fd, "\n");
}
/*
static char** readQuotedList(char* line) {
int n = 0;
char** list = xCalloc(sizeof(char*), 1);
int start = 0;
for (;;) {
while (line[start] && line[start] == ' ') {
start++;
}
if (line[start] != '"') {
break;
}
start++;
int close = start;
while (line[close] && line[close] != '"') {
close++;
}
int len = close - start;
char* item = xMalloc(len + 1);
strncpy(item, line + start, len);
item[len] = '\0';
list[n] = item;
n++;
list = xRealloc(list, sizeof(char*) * (n + 1));
start = close + 1;
}
list[n] = NULL;
return list;
}
static void writeQuotedList(FILE* fd, char** list) {
const char* sep = "";
for (int i = 0; list[i]; i++) {
fprintf(fd, "%s\"%s\"", sep, list[i]);
sep = " ";
}
fprintf(fd, "\n");
}
*/
void Settings_delete(Settings* this) { void Settings_delete(Settings* this) {
free(this->filename); free(this->filename);
free(this->fields); for (unsigned int i = 0; i < (sizeof(this->meterColumns)/sizeof(MeterColumnSettings)); i++) {
for (unsigned int i = 0; i < (sizeof(this->columns)/sizeof(MeterColumnSettings)); i++) { String_freeArray(this->meterColumns[i].names);
String_freeArray(this->columns[i].names); free(this->meterColumns[i].modes);
free(this->columns[i].modes); }
if (this->screens) {
for (unsigned int i = 0; this->screens[i]; i++) {
free(this->screens[i]->name);
free(this->screens[i]->fields);
}
free(this->screens);
} }
free(this); free(this);
} }
static void Settings_readMeters(Settings* this, char* line, int column) { static void Settings_readMeters(Settings* this, char* line, int side) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; int nIds;
char** ids = String_split(trim, ' ', &nIds); char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
this->columns[column].names = ids; this->meterColumns[side].names = ids;
} }
static void Settings_readMeterModes(Settings* this, char* line, int column) { static void Settings_readMeterModes(Settings* this, char* line, int side) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; int nIds;
char** ids = String_split(trim, ' ', &nIds); char** ids = String_split(trim, ' ', &nIds);
@ -44,13 +168,13 @@ static void Settings_readMeterModes(Settings* this, char* line, int column) {
for (int i = 0; ids[i]; i++) { for (int i = 0; ids[i]; i++) {
len++; len++;
} }
this->columns[column].len = len; this->meterColumns[side].len = len;
int* modes = xCalloc(len, sizeof(int)); int* modes = xCalloc(len, sizeof(int));
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
modes[i] = atoi(ids[i]); modes[i] = atoi(ids[i]);
} }
String_freeArray(ids); String_freeArray(ids);
this->columns[column].modes = modes; this->meterColumns[side].modes = modes;
} }
static void Settings_defaultMeters(Settings* this) { static void Settings_defaultMeters(Settings* this) {
@ -59,35 +183,62 @@ static void Settings_defaultMeters(Settings* this) {
sizes[1]++; sizes[1]++;
} }
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
this->columns[i].names = xCalloc(sizes[i] + 1, sizeof(char*)); this->meterColumns[i].names = xCalloc(sizes[i] + 1, sizeof(char*));
this->columns[i].modes = xCalloc(sizes[i], sizeof(int)); this->meterColumns[i].modes = xCalloc(sizes[i], sizeof(int));
this->columns[i].len = sizes[i]; this->meterColumns[i].len = sizes[i];
} }
int r = 0; int r = 0;
if (this->cpuCount > 8) { if (this->cpuCount > 8) {
this->columns[0].names[0] = xStrdup("LeftCPUs2"); this->meterColumns[0].names[0] = xStrdup("LeftCPUs2");
this->columns[0].modes[0] = BAR_METERMODE; this->meterColumns[0].modes[0] = BAR_METERMODE;
this->columns[1].names[r] = xStrdup("RightCPUs2"); this->meterColumns[1].names[r] = xStrdup("RightCPUs2");
this->columns[1].modes[r++] = BAR_METERMODE; this->meterColumns[1].modes[r++] = BAR_METERMODE;
} else if (this->cpuCount > 4) { } else if (this->cpuCount > 4) {
this->columns[0].names[0] = xStrdup("LeftCPUs"); this->meterColumns[0].names[0] = xStrdup("LeftCPUs");
this->columns[0].modes[0] = BAR_METERMODE; this->meterColumns[0].modes[0] = BAR_METERMODE;
this->columns[1].names[r] = xStrdup("RightCPUs"); this->meterColumns[1].names[r] = xStrdup("RightCPUs");
this->columns[1].modes[r++] = BAR_METERMODE; this->meterColumns[1].modes[r++] = BAR_METERMODE;
} else { } else {
this->columns[0].names[0] = xStrdup("AllCPUs"); this->meterColumns[0].names[0] = xStrdup("AllCPUs");
this->columns[0].modes[0] = BAR_METERMODE; this->meterColumns[0].modes[0] = BAR_METERMODE;
} }
this->columns[0].names[1] = xStrdup("Memory"); this->meterColumns[0].names[1] = xStrdup("Memory");
this->columns[0].modes[1] = BAR_METERMODE; this->meterColumns[0].modes[1] = BAR_METERMODE;
this->columns[0].names[2] = xStrdup("Swap"); this->meterColumns[0].names[2] = xStrdup("Swap");
this->columns[0].modes[2] = BAR_METERMODE; this->meterColumns[0].modes[2] = BAR_METERMODE;
this->columns[1].names[r] = xStrdup("Tasks");
this->columns[1].modes[r++] = TEXT_METERMODE; this->meterColumns[1].names[r] = xStrdup("Tasks");
this->columns[1].names[r] = xStrdup("LoadAverage"); this->meterColumns[1].modes[r++] = TEXT_METERMODE;
this->columns[1].modes[r++] = TEXT_METERMODE; this->meterColumns[1].names[r] = xStrdup("LoadAverage");
this->columns[1].names[r] = xStrdup("Uptime"); this->meterColumns[1].modes[r++] = TEXT_METERMODE;
this->columns[1].modes[r++] = TEXT_METERMODE; this->meterColumns[1].names[r] = xStrdup("Uptime");
this->meterColumns[1].modes[r++] = TEXT_METERMODE;
}
static const char* toFieldName(int i) {
if (i < 0 || i > LAST_PROCESSFIELD) {
return "";
}
return Process_fields[i].name;
}
static int toFieldIndex(const char* str) {
if (isdigit(str[0])) {
// This "+1" is for compatibility with the older enum format.
int id = atoi(str) + 1;
if (id < Platform_numberOfFields && toFieldName(id)) {
return id;
}
} else {
for (int p = 1; p < LAST_PROCESSFIELD; p++) {
const char* pName = toFieldName(p);
if (pName && strcmp(pName, str) == 0) {
return p;
}
}
}
return -1;
} }
static void readFields(ProcessField* fields, int* flags, const char* line) { static void readFields(ProcessField* fields, int* flags, const char* line) {
@ -98,11 +249,10 @@ static void readFields(ProcessField* fields, int* flags, const char* line) {
int i, j; int i, j;
*flags = 0; *flags = 0;
for (j = 0, i = 0; i < Platform_numberOfFields && ids[i]; i++) { for (j = 0, i = 0; i < Platform_numberOfFields && ids[i]; i++) {
// This "+1" is for compatibility with the older enum format. int idx = toFieldIndex(ids[i]);
int id = atoi(ids[i]) + 1; if (idx != -1) {
if (id > 0 && Process_fields[id].name && id < Platform_numberOfFields) { fields[j] = idx;
fields[j] = id; *flags |= Process_fields[idx].flags;
*flags |= Process_fields[id].flags;
j++; j++;
} }
} }
@ -110,15 +260,44 @@ static void readFields(ProcessField* fields, int* flags, const char* line) {
String_freeArray(ids); String_freeArray(ids);
} }
ScreenSettings* Settings_newScreen(Settings* this, const char* name, const char* line) {
ScreenSettings* ss = xCalloc(sizeof(ScreenSettings), 1);
ss->name = xStrdup(name);
ss->fields = xCalloc(Platform_numberOfFields+1, sizeof(ProcessField));
ss->flags = 0;
ss->direction = 1;
ss->treeView = 0;
readFields(ss->fields, &(ss->flags), line);
ss->sortKey = ss->fields[0];
this->screens[this->nScreens] = ss;
this->nScreens++;
this->screens = xRealloc(this->screens, sizeof(ScreenSettings*) * (this->nScreens + 1));
this->screens[this->nScreens] = NULL;
return ss;
}
static void Settings_defaultScreens(Settings* this) {
for (unsigned int i = 0; i < Platform_numberOfDefaultScreens; i++) {
ScreenDefaults* defaults = &Platform_defaultScreens[i];
Settings_newScreen(this, defaults->name, defaults->columns);
this->screens[i]->sortKey = toFieldIndex(defaults->sortKey);
}
}
static bool Settings_read(Settings* this, const char* fileName) { static bool Settings_read(Settings* this, const char* fileName) {
FILE* fd; FILE* fd;
CRT_dropPrivileges(); CRT_dropPrivileges();
fd = fopen(fileName, "r"); fd = fopen(fileName, "r");
CRT_restorePrivileges(); CRT_restorePrivileges();
if (!fd) if (!fd)
return false; return false;
bool didReadMeters = false; bool didReadMeters = false;
bool didReadFields = false; bool didReadFields = false;
ProcessField* legacyFields = xCalloc(Platform_numberOfFields+1, sizeof(ProcessField));
int legacyFlags;
bool legacyFieldsRead = false;
for (;;) { for (;;) {
char* line = String_readLine(fd); char* line = String_readLine(fd);
if (!line) { if (!line) {
@ -132,15 +311,8 @@ static bool Settings_read(Settings* this, const char* fileName) {
continue; continue;
} }
if (String_eq(option[0], "fields")) { if (String_eq(option[0], "fields")) {
readFields(this->fields, &(this->flags), option[1]); readFields(legacyFields, &legacyFlags, option[1]);
didReadFields = true; legacyFieldsRead = true;
} else if (String_eq(option[0], "sort_key")) {
// This "+1" is for compatibility with the older enum format.
this->sortKey = atoi(option[1]) + 1;
} else if (String_eq(option[0], "sort_direction")) {
this->direction = atoi(option[1]);
} else if (String_eq(option[0], "tree_view")) {
this->treeView = atoi(option[1]);
} else if (String_eq(option[0], "hide_threads")) { } else if (String_eq(option[0], "hide_threads")) {
this->hideThreads = atoi(option[1]); this->hideThreads = atoi(option[1]);
} else if (String_eq(option[0], "hide_kernel_threads")) { } else if (String_eq(option[0], "hide_kernel_threads")) {
@ -161,6 +333,8 @@ static bool Settings_read(Settings* this, const char* fileName) {
this->highlightThreads = atoi(option[1]); this->highlightThreads = atoi(option[1]);
} else if (String_eq(option[0], "header_margin")) { } else if (String_eq(option[0], "header_margin")) {
this->headerMargin = atoi(option[1]); this->headerMargin = atoi(option[1]);
} else if (String_eq(option[0], "screen_tabs")) {
this->screenTabs = atoi(option[1]);
} else if (String_eq(option[0], "expand_system_time")) { } else if (String_eq(option[0], "expand_system_time")) {
// Compatibility option. // Compatibility option.
this->detailedCPUTime = atoi(option[1]); this->detailedCPUTime = atoi(option[1]);
@ -168,10 +342,6 @@ static bool Settings_read(Settings* this, const char* fileName) {
this->detailedCPUTime = atoi(option[1]); this->detailedCPUTime = atoi(option[1]);
} else if (String_eq(option[0], "cpu_count_from_zero")) { } else if (String_eq(option[0], "cpu_count_from_zero")) {
this->countCPUsFromZero = atoi(option[1]); this->countCPUsFromZero = atoi(option[1]);
} else if (String_eq(option[0], "show_cpu_usage")) {
this->showCPUUsage = atoi(option[1]);
} else if (String_eq(option[0], "show_cpu_frequency")) {
this->showCPUFrequency = atoi(option[1]);
} else if (String_eq(option[0], "update_process_names")) { } else if (String_eq(option[0], "update_process_names")) {
this->updateProcessNames = atoi(option[1]); this->updateProcessNames = atoi(option[1]);
} else if (String_eq(option[0], "account_guest_in_cpu_meter")) { } else if (String_eq(option[0], "account_guest_in_cpu_meter")) {
@ -181,8 +351,6 @@ static bool Settings_read(Settings* this, const char* fileName) {
} else if (String_eq(option[0], "color_scheme")) { } else if (String_eq(option[0], "color_scheme")) {
this->colorScheme = atoi(option[1]); this->colorScheme = atoi(option[1]);
if (this->colorScheme < 0 || this->colorScheme >= LAST_COLORSCHEME) this->colorScheme = 0; if (this->colorScheme < 0 || this->colorScheme >= LAST_COLORSCHEME) this->colorScheme = 0;
} else if (String_eq(option[0], "enable_mouse")) {
this->enableMouse = atoi(option[1]);
} else if (String_eq(option[0], "left_meters")) { } else if (String_eq(option[0], "left_meters")) {
Settings_readMeters(this, option[1], 0); Settings_readMeters(this, option[1], 0);
didReadMeters = true; didReadMeters = true;
@ -195,44 +363,62 @@ static bool Settings_read(Settings* this, const char* fileName) {
} else if (String_eq(option[0], "right_meter_modes")) { } else if (String_eq(option[0], "right_meter_modes")) {
Settings_readMeterModes(this, option[1], 1); Settings_readMeterModes(this, option[1], 1);
didReadMeters = true; didReadMeters = true;
#ifdef HAVE_LIBHWLOC } else if (strncmp(option[0], "screen:", 7) == 0) {
} else if (String_eq(option[0], "topology_affinity")) { Settings_newScreen(this, option[0] + 7, option[1]);
this->topologyAffinity = !!atoi(option[1]); didReadFields = true;
#endif } else if (String_eq(option[0], ".tree_view")) {
if (this->nScreens > 0) {
this->screens[this->nScreens - 1]->treeView = atoi(option[1]);
}
} else if (String_eq(option[0], ".sort_direction")) {
if (this->nScreens > 0) {
this->screens[this->nScreens - 1]->direction = atoi(option[1]);
}
} else if (String_eq(option[0], ".sort_key")) {
if (this->nScreens > 0) {
this->screens[this->nScreens - 1]->sortKey = toFieldIndex(option[1]);
}
} }
String_freeArray(option); String_freeArray(option);
} }
fclose(fd); fclose(fd);
if (this->nScreens == 0) {
Settings_defaultScreens(this);
if (legacyFieldsRead) {
didReadFields = true;
free(this->screens[0]->fields);
this->screens[0]->fields = legacyFields;
this->screens[0]->flags = legacyFlags;
}
}
if (!didReadMeters) { if (!didReadMeters) {
Settings_defaultMeters(this); Settings_defaultMeters(this);
} }
return didReadFields; return didReadFields;
} }
static void writeFields(FILE* fd, ProcessField* fields, const char* name) { static void writeFields(FILE* fd, ProcessField* fields, bool byName) {
fprintf(fd, "%s=", name);
const char* sep = ""; const char* sep = "";
for (int i = 0; fields[i]; i++) { for (int i = 0; fields[i]; i++) {
if (byName) {
fprintf(fd, "%s%s", sep, toFieldName(fields[i]));
} else {
// This " - 1" is for compatibility with the older enum format. // This " - 1" is for compatibility with the older enum format.
fprintf(fd, "%s%d", sep, (int) fields[i] - 1); fprintf(fd, "%s%d", sep, (int) fields[i] - 1);
}
sep = " "; sep = " ";
} }
fprintf(fd, "\n"); fprintf(fd, "\n");
} }
static void writeMeters(Settings* this, FILE* fd, int column) { static void writeMeters(Settings* this, FILE* fd, int side) {
const char* sep = ""; writeList(fd, this->meterColumns[side].names, this->meterColumns[side].len);
for (int i = 0; i < this->columns[column].len; i++) {
fprintf(fd, "%s%s", sep, this->columns[column].names[i]);
sep = " ";
}
fprintf(fd, "\n");
} }
static void writeMeterModes(Settings* this, FILE* fd, int column) { static void writeMeterModes(Settings* this, FILE* fd, int side) {
const char* sep = ""; const char* sep = "";
for (int i = 0; i < this->columns[column].len; i++) { for (int i = 0; i < this->meterColumns[side].len; i++) {
fprintf(fd, "%s%d", sep, this->columns[column].modes[i]); fprintf(fd, "%s%d", sep, this->meterColumns[side].modes[i]);
sep = " "; sep = " ";
} }
fprintf(fd, "\n"); fprintf(fd, "\n");
@ -250,10 +436,7 @@ bool Settings_write(Settings* this) {
} }
fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n"); fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n");
fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n"); fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n");
writeFields(fd, this->fields, "fields"); fprintf(fd, "fields="); writeFields(fd, this->screens[0]->fields, false);
// This "-1" is for compatibility with the older enum format.
fprintf(fd, "sort_key=%d\n", (int) this->sortKey-1);
fprintf(fd, "sort_direction=%d\n", (int) this->direction);
fprintf(fd, "hide_threads=%d\n", (int) this->hideThreads); fprintf(fd, "hide_threads=%d\n", (int) this->hideThreads);
fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads); fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads);
fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads); fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads);
@ -263,61 +446,59 @@ bool Settings_write(Settings* this) {
fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName); fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName);
fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes); fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes);
fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads); fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads);
fprintf(fd, "tree_view=%d\n", (int) this->treeView);
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin); fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
fprintf(fd, "screen_tabs=%d\n", (int) this->screenTabs);
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime); fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->countCPUsFromZero); fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->countCPUsFromZero);
fprintf(fd, "show_cpu_usage=%d\n", (int) this->showCPUUsage);
fprintf(fd, "show_cpu_frequency=%d\n", (int) this->showCPUFrequency);
fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames); fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames);
fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter); fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter);
fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme); fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
fprintf(fd, "enable_mouse=%d\n", (int) this->enableMouse);
fprintf(fd, "delay=%d\n", (int) this->delay); fprintf(fd, "delay=%d\n", (int) this->delay);
fprintf(fd, "left_meters="); writeMeters(this, fd, 0); fprintf(fd, "left_meters="); writeMeters(this, fd, 0);
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0); fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
fprintf(fd, "right_meters="); writeMeters(this, fd, 1); fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1); fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
#ifdef HAVE_LIBHWLOC
fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity); // Legacy compatibility with older versions of htop
#endif fprintf(fd, "tree_view=%d\n", (int) this->screens[0]->treeView);
// This "-1" is for compatibility with the older enum format.
fprintf(fd, "sort_key=%d\n", (int) this->screens[0]->sortKey-1);
fprintf(fd, "sort_direction=%d\n", (int) this->screens[0]->direction);
if (this->screens && this->screens[0]) {
for (unsigned int i = 0; i < this->nScreens; i++) {
ScreenSettings* ss = this->screens[i];
fprintf(fd, "screen:%s=", ss->name);
writeFields(fd, ss->fields, true);
fprintf(fd, ".tree_view=%d\n", (int) ss->treeView);
fprintf(fd, ".sort_key=%s\n", toFieldName(ss->sortKey));
fprintf(fd, ".sort_direction=%d\n", (int) ss->direction);
}
}
fclose(fd); fclose(fd);
return true; return true;
} }
Settings* Settings_new(int cpuCount) { Settings* Settings_new(int cpuCount) {
Settings* this = xCalloc(1, sizeof(Settings)); Settings* this = xCalloc(1, sizeof(Settings));
this->sortKey = PERCENT_CPU;
this->direction = 1;
this->hideThreads = false; this->hideThreads = false;
this->shadowOtherUsers = false; this->shadowOtherUsers = false;
this->showThreadNames = false; this->showThreadNames = false;
this->hideKernelThreads = false; this->hideKernelThreads = false;
this->hideUserlandThreads = false; this->hideUserlandThreads = false;
this->treeView = false;
this->highlightBaseName = false; this->highlightBaseName = false;
this->highlightMegabytes = false; this->highlightMegabytes = false;
this->detailedCPUTime = false; this->detailedCPUTime = false;
this->countCPUsFromZero = false; this->countCPUsFromZero = false;
this->showCPUUsage = true;
this->showCPUFrequency = false;
this->updateProcessNames = false; this->updateProcessNames = false;
this->cpuCount = cpuCount; this->cpuCount = cpuCount;
this->showProgramPath = true; this->showProgramPath = true;
this->highlightThreads = true; this->highlightThreads = true;
#ifdef HAVE_LIBHWLOC
this->topologyAffinity = false; this->screens = xCalloc(sizeof(ScreenSettings*), 1);
#endif this->nScreens = 0;
this->fields = xCalloc(Platform_numberOfFields+1, sizeof(ProcessField));
// TODO: turn 'fields' into a Vector,
// (and ProcessFields into proper objects).
this->flags = 0;
ProcessField* defaults = Platform_defaultFields;
for (int i = 0; defaults[i]; i++) {
this->fields[i] = defaults[i];
this->flags |= Process_fields[defaults[i]].flags;
}
char* legacyDotfile = NULL; char* legacyDotfile = NULL;
char* rcfile = getenv("HTOPRC"); char* rcfile = getenv("HTOPRC");
@ -339,6 +520,7 @@ Settings* Settings_new(int cpuCount) {
htopDir = String_cat(home, "/.config/htop"); htopDir = String_cat(home, "/.config/htop");
} }
legacyDotfile = String_cat(home, "/.htoprc"); legacyDotfile = String_cat(home, "/.htoprc");
CRT_dropPrivileges(); CRT_dropPrivileges();
(void) mkdir(configDir, 0700); (void) mkdir(configDir, 0700);
(void) mkdir(htopDir, 0700); (void) mkdir(htopDir, 0700);
@ -353,7 +535,6 @@ Settings* Settings_new(int cpuCount) {
CRT_restorePrivileges(); CRT_restorePrivileges();
} }
this->colorScheme = 0; this->colorScheme = 0;
this->enableMouse = true;
this->changed = false; this->changed = false;
this->delay = DEFAULT_DELAY; this->delay = DEFAULT_DELAY;
bool ok = false; bool ok = false;
@ -378,15 +559,21 @@ Settings* Settings_new(int cpuCount) {
} }
if (!ok) { if (!ok) {
Settings_defaultMeters(this); Settings_defaultMeters(this);
Settings_defaultScreens(this);
this->hideKernelThreads = true; this->hideKernelThreads = true;
this->highlightMegabytes = true; this->highlightMegabytes = true;
this->highlightThreads = true; this->highlightThreads = true;
this->headerMargin = true; this->headerMargin = true;
this->screenTabs = true;
} }
this->ssIndex = 0;
this->ss = this->screens[this->ssIndex];
return this; return this;
} }
void Settings_invertSortOrder(Settings* this) { void ScreenSettings_invertSortOrder(ScreenSettings* this) {
if (this->direction == 1) if (this->direction == 1)
this->direction = -1; this->direction = -1;
else else

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Settings #ifndef HEADER_Settings
#define HEADER_Settings #define HEADER_Settings
/* /*
@ -12,30 +14,44 @@ in the source distribution for its full text.
#include "Process.h" #include "Process.h"
#include <stdbool.h> #include <stdbool.h>
typedef struct {
const char* name;
const char* columns;
const char* sortKey;
} ScreenDefaults;
typedef struct { typedef struct {
int len; int len;
char** names; char** names;
int* modes; int* modes;
} MeterColumnSettings; } MeterColumnSettings;
typedef struct Settings_ { typedef struct {
char* filename; char* name;
MeterColumnSettings columns[2];
ProcessField* fields; ProcessField* fields;
int flags; int flags;
int direction;
ProcessField sortKey;
bool treeView;
} ScreenSettings;
typedef struct Settings_ {
char* filename;
MeterColumnSettings meterColumns[2];
ScreenSettings** screens;
unsigned int nScreens;
unsigned int ssIndex;
ScreenSettings* ss;
int colorScheme; int colorScheme;
int delay; int delay;
int cpuCount; int cpuCount;
int direction;
ProcessField sortKey;
bool countCPUsFromZero; bool countCPUsFromZero;
bool detailedCPUTime; bool detailedCPUTime;
bool showCPUUsage;
bool showCPUFrequency;
bool treeView;
bool showProgramPath; bool showProgramPath;
bool hideThreads; bool hideThreads;
bool shadowOtherUsers; bool shadowOtherUsers;
@ -48,22 +64,28 @@ typedef struct Settings_ {
bool updateProcessNames; bool updateProcessNames;
bool accountGuestInCPUMeter; bool accountGuestInCPUMeter;
bool headerMargin; bool headerMargin;
bool enableMouse; bool screenTabs;
#ifdef HAVE_LIBHWLOC
bool topologyAffinity;
#endif
bool changed; bool changed;
} Settings; } Settings;
#ifndef Settings_cpuId
#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1) #define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1)
#endif
/*
*/
void Settings_delete(Settings* this); void Settings_delete(Settings* this);
ScreenSettings* Settings_newScreen(Settings* this, const char* name, const char* line);
bool Settings_write(Settings* this); bool Settings_write(Settings* this);
Settings* Settings_new(int cpuCount); Settings* Settings_new(int cpuCount);
void Settings_invertSortOrder(Settings* this); void ScreenSettings_invertSortOrder(ScreenSettings* this);
#endif #endif

View File

@ -18,6 +18,14 @@ in the source distribution for its full text.
#include <ctype.h> #include <ctype.h>
/*{
typedef struct SignalItem_ {
const char* name;
int number;
} SignalItem;
}*/
Panel* SignalsPanel_new() { Panel* SignalsPanel_new() {
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Send ", "Cancel ")); Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Send ", "Cancel "));

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_SignalsPanel #ifndef HEADER_SignalsPanel
#define HEADER_SignalsPanel #define HEADER_SignalsPanel
/* /*
@ -7,11 +9,13 @@ 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.
*/ */
typedef struct SignalItem_ { typedef struct SignalItem_ {
const char* name; const char* name;
int number; int number;
} SignalItem; } SignalItem;
Panel* SignalsPanel_new(); Panel* SignalsPanel_new();
#endif #endif

View File

@ -14,13 +14,24 @@ in the source distribution for its full text.
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
/*{
#include <stdio.h>
#define String_startsWith(s, match) (strncmp((s),(match),strlen(match)) == 0)
#define String_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
}*/
/*
* String_startsWith gives better performance if strlen(match) can be computed
* at compile time (e.g. when they are immutable string literals). :)
*/
char* String_cat(const char* s1, const char* s2) { char* String_cat(const char* s1, const char* s2) {
int l1 = strlen(s1); size_t l1 = strlen(s1);
int l2 = strlen(s2); size_t l2 = strlen(s2);
char* out = xMalloc(l1 + l2 + 1); char* out = xMalloc(l1 + l2 + 1);
memcpy(out, s1, l1); strncpy(out, s1, l1);
memcpy(out+l1, s2, l2+1); strncpy(out + l1, s2, l2 + 1);
out[l1 + l2] = '\0';
return out; return out;
} }
@ -28,7 +39,7 @@ char* String_trim(const char* in) {
while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') { while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') {
in++; in++;
} }
int len = strlen(in); size_t len = strlen(in);
while (len > 0 && (in[len-1] == ' ' || in[len-1] == '\t' || in[len-1] == '\n')) { while (len > 0 && (in[len-1] == ' ' || in[len-1] == '\t' || in[len-1] == '\n')) {
len--; len--;
} }
@ -69,7 +80,10 @@ char** String_split(const char* s, char sep, int* n) {
s += size + 1; s += size + 1;
} }
if (s[0] != '\0') { if (s[0] != '\0') {
out[ctr] = xStrdup(s); size_t size = strlen(s);
char* token = xMalloc(size + 1);
strncpy(token, s, size + 1);
out[ctr] = token;
ctr++; ctr++;
} }
out = xRealloc(out, sizeof(char*) * (ctr + 1)); out = xRealloc(out, sizeof(char*) * (ctr + 1));

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_StringUtils #ifndef HEADER_StringUtils
#define HEADER_StringUtils #define HEADER_StringUtils
/* /*
@ -21,7 +23,7 @@ char* String_cat(const char* s1, const char* s2);
char* String_trim(const char* in); char* String_trim(const char* in);
int String_eq(const char* s1, const char* s2); extern int String_eq(const char* s1, const char* s2);
char** String_split(const char* s, char sep, int* n); char** String_split(const char* s, char sep, int* n);

View File

@ -16,6 +16,9 @@ in the source distribution for its full text.
#include <sys/param.h> #include <sys/param.h>
#include <assert.h> #include <assert.h>
/*{
#include "Meter.h"
}*/
int SwapMeter_attributes[] = { int SwapMeter_attributes[] = {
SWAP SWAP

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_SwapMeter #ifndef HEADER_SwapMeter
#define HEADER_SwapMeter #define HEADER_SwapMeter
/* /*

View File

@ -152,3 +152,4 @@ STrace screen:
LSOF screen: LSOF screen:
TODO TODO

View File

@ -10,9 +10,12 @@ in the source distribution for its full text.
#include "Platform.h" #include "Platform.h"
#include "CRT.h" #include "CRT.h"
/*{
#include "Meter.h"
}*/
int TasksMeter_attributes[] = { int TasksMeter_attributes[] = {
CPU_SYSTEM, PROCESS_THREAD, PROCESS, TASKS_RUNNING CPU_KERNEL, PROCESS_THREAD, PROCESS, TASKS_RUNNING
}; };
static void TasksMeter_updateValues(Meter* this, char* buffer, int len) { static void TasksMeter_updateValues(Meter* this, char* buffer, int len) {
@ -20,7 +23,7 @@ static void TasksMeter_updateValues(Meter* this, char* buffer, int len) {
this->values[0] = pl->kernelThreads; this->values[0] = pl->kernelThreads;
this->values[1] = pl->userlandThreads; this->values[1] = pl->userlandThreads;
this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads; this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads;
this->values[3] = MINIMUM(pl->runningTasks, pl->cpuCount); this->values[3] = MIN(pl->runningTasks, pl->cpuCount);
if (pl->totalTasks > this->total) { if (pl->totalTasks > this->total) {
this->total = pl->totalTasks; this->total = pl->totalTasks;
} }

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_TasksMeter #ifndef HEADER_TasksMeter
#define HEADER_TasksMeter #define HEADER_TasksMeter
/* /*

View File

@ -8,6 +8,7 @@ in the source distribution for its full text.
#include "TraceScreen.h" #include "TraceScreen.h"
#include "CRT.h" #include "CRT.h"
#include "InfoScreen.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "ListItem.h" #include "ListItem.h"
#include "IncSet.h" #include "IncSet.h"
@ -26,6 +27,21 @@ in the source distribution for its full text.
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h> #include <signal.h>
/*{
#include "InfoScreen.h"
typedef struct TraceScreen_ {
InfoScreen super;
bool tracing;
int fdpair[2];
int child;
FILE* strace;
int fd_strace;
bool contLine;
bool follow;
} TraceScreen;
}*/
static const char* const TraceScreenFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL}; static const char* const TraceScreenFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL};
@ -70,7 +86,7 @@ void TraceScreen_draw(InfoScreen* this) {
mvhline(0, 0, ' ', COLS); mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm); mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
attrset(CRT_colors[DEFAULT_COLOR]); attrset(CRT_colors[DEFAULT_COLOR]);
IncSet_drawBar(this->inc); IncSet_drawBar(this->inc, CRT_colors[FUNCTION_BAR]);
} }
bool TraceScreen_forkTracer(TraceScreen* this) { bool TraceScreen_forkTracer(TraceScreen* this) {
@ -85,7 +101,7 @@ bool TraceScreen_forkTracer(TraceScreen* this) {
int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK); int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK);
if (ok != -1) { if (ok != -1) {
xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid); xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid);
execlp("strace", "strace", "-T", "-tt", "-s", "512", "-p", buffer, NULL); execlp("strace", "strace", "-s", "512", "-p", buffer, NULL);
} }
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
ssize_t written = write(this->fdpair[1], message, strlen(message)); ssize_t written = write(this->fdpair[1], message, strlen(message));

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_TraceScreen #ifndef HEADER_TraceScreen
#define HEADER_TraceScreen #define HEADER_TraceScreen
/* /*

View File

@ -9,6 +9,9 @@ in the source distribution for its full text.
#include "Platform.h" #include "Platform.h"
#include "CRT.h" #include "CRT.h"
/*{
#include "Meter.h"
}*/
int UptimeMeter_attributes[] = { int UptimeMeter_attributes[] = {
UPTIME UPTIME

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_UptimeMeter #ifndef HEADER_UptimeMeter
#define HEADER_UptimeMeter #define HEADER_UptimeMeter
/* /*

View File

@ -18,6 +18,13 @@ in the source distribution for its full text.
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
/*{
#include "Hashtable.h"
typedef struct UsersTable_ {
Hashtable* users;
} UsersTable;
}*/
UsersTable* UsersTable_new() { UsersTable* UsersTable_new() {
UsersTable* this; UsersTable* this;

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_UsersTable #ifndef HEADER_UsersTable
#define HEADER_UsersTable #define HEADER_UsersTable
/* /*
@ -19,6 +21,6 @@ void UsersTable_delete(UsersTable* this);
char* UsersTable_getRef(UsersTable* this, unsigned int uid); char* UsersTable_getRef(UsersTable* this, unsigned int uid);
void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData); extern void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData);
#endif #endif

View File

@ -12,6 +12,25 @@ in the source distribution for its full text.
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
/*{
#include "Object.h"
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)
#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1
#endif
typedef struct Vector_ {
Object **array;
ObjectClass* type;
int arraySize;
int growthRate;
int items;
bool owner;
} Vector;
}*/
Vector* Vector_new(ObjectClass* type, bool owner, int size) { Vector* Vector_new(ObjectClass* type, bool owner, int size) {
Vector* this; Vector* this;
@ -261,7 +280,7 @@ inline Object* Vector_get(Vector* this, int idx) {
#else #else
// In this case, Vector_get is defined as a macro in vector.h #define Vector_get(v_, idx_) ((v_)->array[idx_])
#endif #endif
@ -274,7 +293,7 @@ inline int Vector_size(Vector* this) {
#else #else
// In this case, Vector_size is defined as a macro in vector.h #define Vector_size(v_) ((v_)->items)
#endif #endif
@ -316,15 +335,3 @@ inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
} }
return -1; return -1;
} }
void Vector_splice(Vector* this, Vector* from) {
assert(Vector_isConsistent(this));
assert(Vector_isConsistent(from));
assert(!(this->owner && from->owner));
int olditmes = this->items;
this->items += from->items;
Vector_checkArraySize(this);
for (int j = 0; j < from->items; j++)
this->array[olditmes + j] = from->array[j];
}

View File

@ -1,3 +1,5 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Vector #ifndef HEADER_Vector
#define HEADER_Vector #define HEADER_Vector
/* /*
@ -24,6 +26,7 @@ typedef struct Vector_ {
bool owner; bool owner;
} Vector; } Vector;
Vector* Vector_new(ObjectClass* type, bool owner, int size); Vector* Vector_new(ObjectClass* type, bool owner, int size);
void Vector_delete(Vector* this); void Vector_delete(Vector* this);
@ -36,6 +39,11 @@ int Vector_count(Vector* this);
void Vector_prune(Vector* this); void Vector_prune(Vector* this);
// If I were to use only one sorting algorithm for both cases, it would probably be this one:
/*
*/
void Vector_quickSort(Vector* this); void Vector_quickSort(Vector* this);
void Vector_insertionSort(Vector* this); void Vector_insertionSort(Vector* this);
@ -54,7 +62,7 @@ void Vector_set(Vector* this, int idx, void* data_);
#ifdef DEBUG #ifdef DEBUG
Object* Vector_get(Vector* this, int idx); extern Object* Vector_get(Vector* this, int idx);
#else #else
@ -64,7 +72,7 @@ Object* Vector_get(Vector* this, int idx);
#ifdef DEBUG #ifdef DEBUG
int Vector_size(Vector* this); extern int Vector_size(Vector* this);
#else #else
@ -72,10 +80,12 @@ int Vector_size(Vector* this);
#endif #endif
/*
*/
void Vector_add(Vector* this, void* data_); void Vector_add(Vector* this, void* data_);
int Vector_indexOf(Vector* this, void* search_, Object_Compare compare); extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
void Vector_splice(Vector* this, Vector* from);
#endif #endif

View File

@ -8,8 +8,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/*{
#include <err.h>
#include <assert.h>
#include <stdlib.h>
}*/
void fail() { static inline void fail() {
curs_set(1); curs_set(1);
endwin(); endwin();
err(1, NULL); err(1, NULL);
@ -39,10 +44,6 @@ void* xRealloc(void* ptr, size_t size) {
return data; return data;
} }
#undef xAsprintf
#define xAsprintf(strp, fmt, ...) do { int _r=asprintf(strp, fmt, __VA_ARGS__); if (_r < 0) { fail(); } } while(0)
#define xSnprintf(fmt, len, ...) do { int _l=len; int _n=snprintf(fmt, _l, __VA_ARGS__); if (!(_n > -1 && _n < _l)) { curs_set(1); endwin(); err(1, NULL); } } while(0) #define xSnprintf(fmt, len, ...) do { int _l=len; int _n=snprintf(fmt, _l, __VA_ARGS__); if (!(_n > -1 && _n < _l)) { curs_set(1); endwin(); err(1, NULL); } } while(0)
#undef xStrdup #undef xStrdup

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