mirror of https://github.com/xzeldon/htop.git
Merge branch 'hili-new-old' of adsr/htop into highlight-new-old-processes
This commit is contained in:
commit
0951090fa4
12
CRT.c
12
CRT.c
|
@ -112,6 +112,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||
[PROCESS_THREAD] = ColorPair(Green, Black),
|
||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black),
|
||||
[BAR_BORDER] = A_BOLD,
|
||||
|
@ -191,6 +193,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD,
|
||||
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
||||
[PROCESS_LOW_PRIORITY] = A_DIM,
|
||||
[PROCESS_NEW] = A_BOLD,
|
||||
[PROCESS_TOMB] = A_DIM,
|
||||
[PROCESS_THREAD] = A_BOLD,
|
||||
[PROCESS_THREAD_BASENAME] = A_REVERSE,
|
||||
[BAR_BORDER] = A_BOLD,
|
||||
|
@ -270,6 +274,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White),
|
||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, White),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, White),
|
||||
[PROCESS_NEW] = ColorPair(White,Green),
|
||||
[PROCESS_TOMB] = ColorPair(White,Red),
|
||||
[PROCESS_THREAD] = ColorPair(Blue, White),
|
||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, White),
|
||||
[BAR_BORDER] = ColorPair(Blue, White),
|
||||
|
@ -349,6 +355,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||
[PROCESS_THREAD] = ColorPair(Blue, Black),
|
||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black),
|
||||
[BAR_BORDER] = ColorPair(Blue, Black),
|
||||
|
@ -428,6 +436,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue),
|
||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue),
|
||||
[PROCESS_NEW] = ColorPair(Blue,Green),
|
||||
[PROCESS_TOMB] = ColorPair(Blue,Red),
|
||||
[PROCESS_THREAD] = ColorPair(Green, Blue),
|
||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Blue),
|
||||
[BAR_BORDER] = A_BOLD | ColorPair(Yellow, Blue),
|
||||
|
@ -509,6 +519,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||
[BAR_BORDER] = A_BOLD | ColorPair(Green, Black),
|
||||
[BAR_SHADOW] = ColorPair(Cyan, Black),
|
||||
[SWAP] = ColorPair(Red, Black),
|
||||
|
|
2
CRT.h
2
CRT.h
|
@ -73,6 +73,8 @@ typedef enum ColorElements_ {
|
|||
PROCESS_BASENAME,
|
||||
PROCESS_HIGH_PRIORITY,
|
||||
PROCESS_LOW_PRIORITY,
|
||||
PROCESS_NEW,
|
||||
PROCESS_TOMB,
|
||||
PROCESS_THREAD,
|
||||
PROCESS_THREAD_BASENAME,
|
||||
BAR_BORDER,
|
||||
|
|
|
@ -93,6 +93,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
|||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage)));
|
||||
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)));
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Highlight new and old processes"), &(settings->highlightChanges)));
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity)));
|
||||
#endif
|
||||
|
|
12
Panel.c
12
Panel.c
|
@ -273,16 +273,18 @@ void Panel_draw(Panel* this, bool focus) {
|
|||
Object_display(itemObj, &item);
|
||||
int itemLen = RichString_sizeVal(item);
|
||||
int amt = MINIMUM(itemLen - scrollH, this->w);
|
||||
bool selected = (i == this->selected);
|
||||
if (selected) {
|
||||
attrset(selectionColor);
|
||||
RichString_setAttr(&item, selectionColor);
|
||||
if (i == this->selected) {
|
||||
item.highlightAttr = selectionColor;
|
||||
}
|
||||
if (item.highlightAttr) {
|
||||
attrset(item.highlightAttr);
|
||||
RichString_setAttr(&item, item.highlightAttr);
|
||||
this->selectedLen = itemLen;
|
||||
}
|
||||
mvhline(y + line, x, ' ', this->w);
|
||||
if (amt > 0)
|
||||
RichString_printoffnVal(item, y + line, x, scrollH, amt);
|
||||
if (selected)
|
||||
if (item.highlightAttr)
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(item);
|
||||
line++;
|
||||
|
|
48
Process.c
48
Process.c
|
@ -76,7 +76,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori
|
|||
RichString_appendn(str, processColor, buffer, len);
|
||||
} else if (number < 100000) {
|
||||
//2 digit MB, 3 digit KB
|
||||
len = snprintf(buffer, 10, "%2llu", number / 1000);
|
||||
len = snprintf(buffer, 10, "%2llu", number/1000);
|
||||
RichString_appendn(str, processMegabytesColor, buffer, len);
|
||||
number %= 1000;
|
||||
len = snprintf(buffer, 10, "%03llu ", number);
|
||||
|
@ -89,7 +89,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori
|
|||
} else if (number < 10000 * ONE_K) {
|
||||
//1 digit GB, 3 digit MB
|
||||
number /= ONE_K;
|
||||
len = snprintf(buffer, 10, "%1llu", number / 1000);
|
||||
len = snprintf(buffer, 10, "%1llu", number/1000);
|
||||
RichString_appendn(str, processGigabytesColor, buffer, len);
|
||||
number %= 1000;
|
||||
len = snprintf(buffer, 10, "%03lluM ", number);
|
||||
|
@ -97,7 +97,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori
|
|||
} else if (number < 100000 * ONE_K) {
|
||||
//2 digit GB, 1 digit MB
|
||||
number /= 100 * ONE_K;
|
||||
len = snprintf(buffer, 10, "%2llu", number / 10);
|
||||
len = snprintf(buffer, 10, "%2llu", number/10);
|
||||
RichString_appendn(str, processGigabytesColor, buffer, len);
|
||||
number %= 10;
|
||||
len = snprintf(buffer, 10, ".%1lluG ", number);
|
||||
|
@ -110,14 +110,14 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori
|
|||
} else if (number < 10000ULL * ONE_M) {
|
||||
//1 digit TB, 3 digit GB
|
||||
number /= ONE_M;
|
||||
len = snprintf(buffer, 10, "%1llu", number / 1000);
|
||||
len = snprintf(buffer, 10, "%1llu", number/1000);
|
||||
RichString_appendn(str, largeNumberColor, buffer, len);
|
||||
number %= 1000;
|
||||
len = snprintf(buffer, 10, "%03lluG ", number);
|
||||
RichString_appendn(str, processGigabytesColor, buffer, len);
|
||||
} else {
|
||||
//2 digit TB and above
|
||||
len = snprintf(buffer, 10, "%4.1lfT ", (double)number / ONE_G);
|
||||
len = snprintf(buffer, 10, "%4.1lfT ", (double)number/ONE_G);
|
||||
RichString_appendn(str, largeNumberColor, buffer, len);
|
||||
}
|
||||
}
|
||||
|
@ -144,18 +144,18 @@ void Process_colorNumber(RichString* str, unsigned long long number, bool colori
|
|||
} 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);
|
||||
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, processMegabytesColor, buffer + 5, 3);
|
||||
RichString_appendn(str, processColor, buffer + 8, 4);
|
||||
RichString_appendn(str, processMegabytesColor, buffer+5, 3);
|
||||
RichString_appendn(str, processColor, buffer+8, 4);
|
||||
} else {
|
||||
xSnprintf(buffer, 13, "%11llu ", number);
|
||||
RichString_appendn(str, largeNumberColor, buffer, 2);
|
||||
RichString_appendn(str, processMegabytesColor, buffer + 2, 3);
|
||||
RichString_appendn(str, processColor, buffer + 5, 3);
|
||||
RichString_appendn(str, processShadowColor, buffer + 8, 4);
|
||||
RichString_appendn(str, processMegabytesColor, buffer+2, 3);
|
||||
RichString_appendn(str, processColor, buffer+5, 3);
|
||||
RichString_appendn(str, processShadowColor, buffer+8, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,11 +291,11 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
|||
|
||||
for (int i = 0; i < 32; 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;
|
||||
if (indent & (1 << i)) {
|
||||
ret = snprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]);
|
||||
|
@ -333,7 +333,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
|||
case PID: xSnprintf(buffer, n, Process_pidFormat, this->pid); break;
|
||||
case PPID: xSnprintf(buffer, n, Process_pidFormat, this->ppid); break;
|
||||
case PRIORITY: {
|
||||
if (this->priority <= -100)
|
||||
if(this->priority <= -100)
|
||||
xSnprintf(buffer, n, " RT ");
|
||||
else
|
||||
xSnprintf(buffer, n, "%3ld ", this->priority);
|
||||
|
@ -394,6 +394,14 @@ void Process_display(const Object* cast, RichString* out) {
|
|||
RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
|
||||
}
|
||||
|
||||
if (this->settings->highlightChanges) {
|
||||
if (Process_isTomb(this)) {
|
||||
out->highlightAttr = CRT_colors[PROCESS_TOMB];
|
||||
} else if (Process_isNew(this)) {
|
||||
out->highlightAttr = CRT_colors[PROCESS_NEW];
|
||||
}
|
||||
}
|
||||
|
||||
assert(out->chlen > 0);
|
||||
}
|
||||
|
||||
|
@ -429,6 +437,18 @@ void Process_toggleTag(Process* this) {
|
|||
this->tag = this->tag == true ? false : true;
|
||||
}
|
||||
|
||||
bool Process_isNew(const Process* this) {
|
||||
assert(this->processList);
|
||||
if (this->processList->scanTs >= this->seenTs) {
|
||||
return this->processList->scanTs - this->seenTs <= this->processList->settings->highlightDelaySecs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Process_isTomb(const Process* this) {
|
||||
return this->tombTs > 0;
|
||||
}
|
||||
|
||||
bool Process_setPriority(Process* this, int priority) {
|
||||
CRT_dropPrivileges();
|
||||
int old_prio = getpriority(PRIO_PROCESS, this->pid);
|
||||
|
|
14
Process.h
14
Process.h
|
@ -9,18 +9,19 @@ in the source distribution for its full text.
|
|||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Object.h"
|
||||
#include "RichString.h"
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define SYS_ioprio_get __NR_ioprio_get
|
||||
#define SYS_ioprio_set __NR_ioprio_set
|
||||
#endif
|
||||
|
||||
#define PROCESS_FLAG_IO 0x0001
|
||||
#define DEFAULT_HIGHLIGHT_SECS 5
|
||||
|
||||
typedef enum ProcessFields {
|
||||
NULL_PROCESSFIELD = 0,
|
||||
|
@ -59,6 +60,7 @@ struct Settings_;
|
|||
typedef struct Process_ {
|
||||
Object super;
|
||||
|
||||
const struct ProcessList_* processList;
|
||||
const struct Settings_* settings;
|
||||
|
||||
unsigned long long int time;
|
||||
|
@ -76,6 +78,7 @@ typedef struct Process_ {
|
|||
bool tag;
|
||||
bool showChildren;
|
||||
bool show;
|
||||
bool wasShown;
|
||||
unsigned int pgrp;
|
||||
unsigned int session;
|
||||
unsigned int tty_nr;
|
||||
|
@ -99,6 +102,9 @@ typedef struct Process_ {
|
|||
|
||||
int exit_signal;
|
||||
|
||||
time_t seenTs;
|
||||
time_t tombTs;
|
||||
|
||||
unsigned long int minflt;
|
||||
unsigned long int majflt;
|
||||
} Process;
|
||||
|
@ -119,7 +125,7 @@ extern ProcessFieldData Process_fields[];
|
|||
extern ProcessPidColumn Process_pidColumns[];
|
||||
extern char Process_pidFormat[20];
|
||||
|
||||
typedef Process* (* Process_New)(const struct Settings_*);
|
||||
typedef Process*(*Process_New)(const struct Settings_*);
|
||||
typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField);
|
||||
|
||||
typedef struct ProcessClass_ {
|
||||
|
@ -172,6 +178,10 @@ void Process_init(Process* this, const struct Settings_* settings);
|
|||
|
||||
void Process_toggleTag(Process* this);
|
||||
|
||||
bool Process_isNew(const Process* this);
|
||||
|
||||
bool Process_isTomb(const Process* this);
|
||||
|
||||
bool Process_setPriority(Process* this, int priority);
|
||||
|
||||
bool Process_changePriorityBy(Process* this, Arg delta);
|
||||
|
|
|
@ -9,6 +9,7 @@ in the source distribution for its full text.
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "CRT.h"
|
||||
#include "XUtils.h"
|
||||
|
@ -27,6 +28,9 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users
|
|||
// set later by platform-specific code
|
||||
this->cpuCount = 0;
|
||||
|
||||
this->scanTs = 0;
|
||||
this->firstScanTs = 0;
|
||||
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
this->topologyOk = false;
|
||||
if (hwloc_topology_init(&this->topology) == 0) {
|
||||
|
@ -85,6 +89,14 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
|
|||
void ProcessList_add(ProcessList* this, Process* p) {
|
||||
assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1);
|
||||
assert(Hashtable_get(this->processTable, p->pid) == NULL);
|
||||
p->processList = this;
|
||||
|
||||
if (this->scanTs == this->firstScanTs) {
|
||||
// prevent highlighting processes found in first scan
|
||||
p->seenTs = this->firstScanTs - this->settings->highlightDelaySecs - 1;
|
||||
} else {
|
||||
p->seenTs = this->scanTs;
|
||||
}
|
||||
|
||||
Vector_add(this->processes, p);
|
||||
Hashtable_put(this->processTable, p->pid, p);
|
||||
|
@ -145,10 +157,10 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
|
|||
Vector_insert(this->processes2, 0, process);
|
||||
}
|
||||
|
||||
assert(Vector_size(this->processes2) == s + 1); (void)s;
|
||||
assert(Vector_size(this->processes2) == s+1); (void)s;
|
||||
|
||||
int nextIndent = indent | (1 << level);
|
||||
ProcessList_buildTree(this, process->pid, level + 1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false);
|
||||
ProcessList_buildTree(this, process->pid, level+1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false);
|
||||
|
||||
if (i == size - 1) {
|
||||
process->indent = -nextIndent;
|
||||
|
@ -160,8 +172,8 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
|
|||
}
|
||||
|
||||
static long ProcessList_treeProcessCompare(const void* v1, const void* v2) {
|
||||
const Process* p1 = (const Process*)v1;
|
||||
const Process* p2 = (const Process*)v2;
|
||||
const Process *p1 = (const Process*)v1;
|
||||
const Process *p2 = (const Process*)v2;
|
||||
|
||||
return p1->pid - p2->pid;
|
||||
}
|
||||
|
@ -304,6 +316,7 @@ Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting,
|
|||
}
|
||||
|
||||
void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
||||
struct timespec now;
|
||||
|
||||
// in pause mode only gather global data for meters (CPU/memory/...)
|
||||
if (pauseProcessUpdate) {
|
||||
|
@ -315,6 +328,7 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
|||
for (int i = 0; i < Vector_size(this->processes); i++) {
|
||||
Process* p = (Process*) Vector_get(this->processes, i);
|
||||
p->updated = false;
|
||||
p->wasShown = p->show;
|
||||
p->show = true;
|
||||
}
|
||||
|
||||
|
@ -323,12 +337,33 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
|||
this->kernelThreads = 0;
|
||||
this->runningTasks = 0;
|
||||
|
||||
|
||||
// set scanTs
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
|
||||
if (this->firstScanTs == 0) {
|
||||
this->firstScanTs = now.tv_sec;
|
||||
}
|
||||
this->scanTs = now.tv_sec;
|
||||
}
|
||||
|
||||
ProcessList_goThroughEntries(this, false);
|
||||
|
||||
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||
Process* p = (Process*) Vector_get(this->processes, i);
|
||||
if (p->updated == false) {
|
||||
if (p->tombTs > 0) {
|
||||
// remove tombed process
|
||||
if (this->scanTs >= p->tombTs) {
|
||||
ProcessList_remove(this, p);
|
||||
}
|
||||
} else if (p->updated == false) {
|
||||
// process no longer exists
|
||||
if (this->settings->highlightChanges && p->wasShown) {
|
||||
// mark tombed
|
||||
p->tombTs = this->scanTs + this->settings->highlightDelaySecs;
|
||||
} else {
|
||||
// immediately remove
|
||||
ProcessList_remove(this, p);
|
||||
}
|
||||
} else {
|
||||
p->updated = false;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ typedef struct ProcessList_ {
|
|||
|
||||
int cpuCount;
|
||||
|
||||
time_t scanTs;
|
||||
time_t firstScanTs;
|
||||
} ProcessList;
|
||||
|
||||
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct RichString_ {
|
|||
int chlen;
|
||||
CharType* chptr;
|
||||
CharType chstr[RICHSTRING_MAXLEN + 1];
|
||||
int highlightAttr;
|
||||
} RichString;
|
||||
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
||||
|
|
|
@ -102,6 +102,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
|
|||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
||||
|
||||
*timedOut = (newTime - *oldTime > this->settings->delay);
|
||||
*rescan |= *timedOut;
|
||||
|
||||
|
|
|
@ -157,6 +157,10 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo
|
|||
this->highlightMegabytes = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "highlight_threads")) {
|
||||
this->highlightThreads = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "highlight_changes")) {
|
||||
this->highlightChanges = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "highlight_changes_delay_secs")) {
|
||||
this->highlightDelaySecs = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "header_margin")) {
|
||||
this->headerMargin = atoi(option[1]);
|
||||
} else if (String_eq(option[0], "expand_system_time")) {
|
||||
|
@ -265,6 +269,8 @@ bool Settings_write(Settings* this) {
|
|||
fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName);
|
||||
fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes);
|
||||
fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads);
|
||||
fprintf(fd, "highlight_changes=%d\n", (int) this->highlightChanges);
|
||||
fprintf(fd, "highlight_changes_delay_secs=%d\n", (int) this->highlightDelaySecs);
|
||||
fprintf(fd, "tree_view=%d\n", (int) this->treeView);
|
||||
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
|
||||
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
|
||||
|
@ -306,6 +312,8 @@ Settings* Settings_new(int initialCpuCount) {
|
|||
this->updateProcessNames = false;
|
||||
this->showProgramPath = true;
|
||||
this->highlightThreads = true;
|
||||
this->highlightChanges = false;
|
||||
this->highlightDelaySecs = DEFAULT_HIGHLIGHT_SECS;
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
this->topologyAffinity = false;
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,8 @@ typedef struct Settings_ {
|
|||
bool highlightBaseName;
|
||||
bool highlightMegabytes;
|
||||
bool highlightThreads;
|
||||
bool highlightChanges;
|
||||
int highlightDelaySecs;
|
||||
bool updateProcessNames;
|
||||
bool accountGuestInCPUMeter;
|
||||
bool headerMargin;
|
||||
|
|
|
@ -4,7 +4,7 @@ htop \- interactive process viewer
|
|||
.SH "SYNOPSIS"
|
||||
.LP
|
||||
.B htop
|
||||
.RB [ \-dCFhpustv ]
|
||||
.RB [ \-dCFhpustvH ]
|
||||
.SH "DESCRIPTION"
|
||||
.LP
|
||||
.B htop
|
||||
|
@ -62,6 +62,9 @@ Output version information and exit
|
|||
.TP
|
||||
\fB\-t \-\-tree
|
||||
Show processes in tree view
|
||||
.TP
|
||||
\fB\-H \-\-highlight-changes=DELAY\fR
|
||||
Highlight new and old processes
|
||||
.SH "INTERACTIVE COMMANDS"
|
||||
.LP
|
||||
The following commands are supported while in
|
||||
|
|
50
htop.c
50
htop.c
|
@ -50,8 +50,9 @@ static void printHelpFlag(void) {
|
|||
"-d --delay=DELAY Set the delay between updates, in tenths of seconds\n"
|
||||
"-F --filter=FILTER Show only the commands matching the given filter\n"
|
||||
"-h --help Print this help screen\n"
|
||||
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
|
||||
"-M --no-mouse Disable the mouse\n"
|
||||
"-p --pid=PID,[,PID,PID...] Show only the given PIDs\n"
|
||||
"-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
|
||||
"-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n"
|
||||
"-t --tree Show the tree view by default\n"
|
||||
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
||||
|
@ -76,6 +77,8 @@ typedef struct CommandLineSettings_ {
|
|||
bool enableMouse;
|
||||
bool treeView;
|
||||
bool allowUnicode;
|
||||
bool highlightChanges;
|
||||
int highlightDelaySecs;
|
||||
} CommandLineSettings;
|
||||
|
||||
static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
|
@ -90,6 +93,8 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||
.enableMouse = true,
|
||||
.treeView = false,
|
||||
.allowUnicode = true,
|
||||
.highlightChanges = false,
|
||||
.highlightDelaySecs = -1,
|
||||
};
|
||||
|
||||
static struct option long_opts[] =
|
||||
|
@ -106,12 +111,13 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||
{"tree", no_argument, 0, 't'},
|
||||
{"pid", required_argument, 0, 'p'},
|
||||
{"filter", required_argument, 0, 'F'},
|
||||
{0, 0, 0, 0}
|
||||
{"highlight-changes", optional_argument, 0, 'H'},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
int opt, opti = 0;
|
||||
int opt, opti=0;
|
||||
/* Parse arguments */
|
||||
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:", long_opts, &opti))) {
|
||||
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) {
|
||||
if (opt == EOF) break;
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
|
@ -186,11 +192,11 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||
char* saveptr;
|
||||
char* pid = strtok_r(argCopy, ",", &saveptr);
|
||||
|
||||
if (!flags.pidMatchList) {
|
||||
if(!flags.pidMatchList) {
|
||||
flags.pidMatchList = Hashtable_new(8, false);
|
||||
}
|
||||
|
||||
while (pid) {
|
||||
while(pid) {
|
||||
unsigned int num_pid = atoi(pid);
|
||||
// deepcode ignore CastIntegerToAddress: we just want a non-NUll pointer here
|
||||
Hashtable_put(flags.pidMatchList, num_pid, (void *) 1);
|
||||
|
@ -206,6 +212,24 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||
|
||||
break;
|
||||
}
|
||||
case 'H': {
|
||||
const char *delay = optarg;
|
||||
if (!delay && optind < argc && argv[optind] != NULL &&
|
||||
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
|
||||
delay = argv[optind++];
|
||||
}
|
||||
if (delay) {
|
||||
if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) {
|
||||
if (flags.highlightDelaySecs < 1)
|
||||
flags.highlightDelaySecs = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
flags.highlightChanges = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
|
@ -218,7 +242,7 @@ static void millisleep(unsigned long millisec) {
|
|||
.tv_sec = 0,
|
||||
.tv_nsec = millisec * 1000000L
|
||||
};
|
||||
while (nanosleep(&req, &req) == -1) {
|
||||
while(nanosleep(&req,&req)==-1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +266,7 @@ static void setCommFilter(State* state, char** commFilter) {
|
|||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
char* lc_ctype = getenv("LC_CTYPE");
|
||||
char *lc_ctype = getenv("LC_CTYPE");
|
||||
if (lc_ctype != NULL) {
|
||||
setlocale(LC_CTYPE, lc_ctype);
|
||||
} else if ((lc_ctype = getenv("LC_ALL"))) {
|
||||
|
@ -284,6 +308,12 @@ int main(int argc, char** argv) {
|
|||
if (flags.treeView) {
|
||||
settings->treeView = true;
|
||||
}
|
||||
if (flags.highlightChanges) {
|
||||
settings->highlightChanges = true;
|
||||
}
|
||||
if (flags.highlightDelaySecs != -1) {
|
||||
settings->highlightDelaySecs = flags.highlightDelaySecs;
|
||||
}
|
||||
|
||||
CRT_init(settings->delay, settings->colorScheme, flags.allowUnicode);
|
||||
|
||||
|
@ -323,7 +353,7 @@ int main(int argc, char** argv) {
|
|||
ScreenManager_run(scr, NULL, NULL);
|
||||
|
||||
attron(CRT_colors[RESET_COLOR]);
|
||||
mvhline(LINES - 1, 0, ' ', COLS);
|
||||
mvhline(LINES-1, 0, ' ', COLS);
|
||||
attroff(CRT_colors[RESET_COLOR]);
|
||||
refresh();
|
||||
|
||||
|
@ -339,7 +369,7 @@ int main(int argc, char** argv) {
|
|||
UsersTable_delete(ut);
|
||||
Settings_delete(settings);
|
||||
|
||||
if (flags.pidMatchList) {
|
||||
if(flags.pidMatchList) {
|
||||
Hashtable_delete(flags.pidMatchList);
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue