summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2014-11-19 23:17:52 -0200
committerHisham Muhammad <hisham@gobolinux.org>2014-11-19 23:17:52 -0200
commit9faf4938b8195a0fb5d62cf1702f9f5c07523031 (patch)
tree84732ab7ef1bf66d55feefaf97216ccfc9bf2fad
parent300af4b829c6552d7efdfcde43220cf318b5a265 (diff)
Refactored key handlers.
Made the logic more modular, hopefully easier to follow, and removed repeated code. Plus, some optimization in RichString code.
-rw-r--r--ProcessList.c8
-rw-r--r--ProcessList.h2
-rw-r--r--RichString.c17
-rw-r--r--RichString.h6
-rw-r--r--ScreenManager.c2
-rw-r--r--htop.c759
-rw-r--r--htop.h29
7 files changed, 457 insertions, 366 deletions
diff --git a/ProcessList.c b/ProcessList.c
index 7559623c..7841e0a3 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -1047,16 +1047,12 @@ void ProcessList_expandTree(ProcessList* this) {
}
}
-void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, bool userOnly, uid_t userId, const char* incFilter) {
+void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, const char* incFilter) {
if (!flags) {
following = this->following;
- userOnly = this->userOnly;
- userId = this->userId;
incFilter = this->incFilter;
} else {
this->following = following;
- this->userOnly = userOnly;
- this->userId = userId;
this->incFilter = incFilter;
}
@@ -1072,7 +1068,7 @@ void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, bool
Process* p = ProcessList_get(this, i);
if ( (!p->show)
- || (userOnly && (p->st_uid != userId))
+ || (this->userOnly && (p->st_uid != this->userId))
|| (incFilter && !(String_contains_i(p->comm, incFilter)))
|| (this->pidWhiteList && !Hashtable_get(this->pidWhiteList, p->pid)) )
hidden = true;
diff --git a/ProcessList.h b/ProcessList.h
index 1f3549ae..fce7d03f 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -183,6 +183,6 @@ ProcessField ProcessList_keyAt(ProcessList* this, int at);
void ProcessList_expandTree(ProcessList* this);
-void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, bool userOnly, uid_t userId, const char* incFilter);
+void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, const char* incFilter);
#endif
diff --git a/RichString.c b/RichString.c
index 34720c1b..fb2f2578 100644
--- a/RichString.c
+++ b/RichString.c
@@ -10,7 +10,7 @@ in the source distribution for its full text.
#include <stdlib.h>
#include <string.h>
-#define RICHSTRING_MAXLEN 300
+#define RICHSTRING_MAXLEN 350
/*{
#include "config.h"
@@ -52,8 +52,8 @@ in the source distribution for its full text.
typedef struct RichString_ {
int chlen;
- CharType chstr[RICHSTRING_MAXLEN+1];
CharType* chptr;
+ CharType chstr[RICHSTRING_MAXLEN+1];
} RichString;
}*/
@@ -64,7 +64,7 @@ typedef struct RichString_ {
#define charBytes(n) (sizeof(CharType) * (n))
-static inline void RichString_setLen(RichString* this, int len) {
+static void RichString_extendLen(RichString* this, int len) {
if (this->chlen <= RICHSTRING_MAXLEN) {
if (len > RICHSTRING_MAXLEN) {
this->chptr = malloc(charBytes(len+1));
@@ -83,6 +83,8 @@ static inline void RichString_setLen(RichString* this, int len) {
this->chlen = len;
}
+#define RichString_setLen(this, len) do{ if(len < RICHSTRING_MAXLEN) { RichString_setChar(this,len,0); this->chlen=len; } else RichString_extendLen(this,len); }while(0)
+
#ifdef HAVE_LIBNCURSESW
static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) {
@@ -92,10 +94,11 @@ static inline void RichString_writeFrom(RichString* this, int attrs, const char*
return;
int newLen = from + len;
RichString_setLen(this, newLen);
- memset(&this->chptr[from], 0, sizeof(CharType) * (newLen - from));
for (int i = from, j = 0; i < newLen; i++, j++) {
- this->chptr[i].chars[0] = data[j];
- this->chptr[i].attr = attrs;
+ CharType* c = &(this->chptr[i]);
+ c->attr = attrs;
+ c->chars[0] = data[j];
+ c->chars[1] = 0;
}
this->chptr[newLen].chars[0] = 0;
}
@@ -171,4 +174,4 @@ void RichString_appendn(RichString* this, int attrs, const char* data, int len)
void RichString_write(RichString* this, int attrs, const char* data) {
RichString_writeFrom(this, attrs, data, 0, strlen(data));
-}
+} \ No newline at end of file
diff --git a/RichString.h b/RichString.h
index a9cb3f6e..971e3acb 100644
--- a/RichString.h
+++ b/RichString.h
@@ -9,7 +9,7 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
-#define RICHSTRING_MAXLEN 300
+#define RICHSTRING_MAXLEN 350
#include "config.h"
#include <ctype.h>
@@ -50,8 +50,8 @@ in the source distribution for its full text.
typedef struct RichString_ {
int chlen;
- CharType chstr[RICHSTRING_MAXLEN+1];
CharType* chptr;
+ CharType chstr[RICHSTRING_MAXLEN+1];
} RichString;
@@ -61,6 +61,8 @@ typedef struct RichString_ {
#define charBytes(n) (sizeof(CharType) * (n))
+#define RichString_setLen(this, len) do{ if(len < RICHSTRING_MAXLEN) { RichString_setChar(this,len,0); this->chlen=len; } else RichString_extendLen(this,len); }while(0)
+
#ifdef HAVE_LIBNCURSESW
extern void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
diff --git a/ScreenManager.c b/ScreenManager.c
index 646ee2f0..e7a0872a 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -144,7 +144,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
this->lastScan = now;
}
Header_draw(this->header);
- ProcessList_rebuildPanel(this->header->pl, false, false, false, false, NULL);
+ ProcessList_rebuildPanel(this->header->pl, false, false, NULL);
}
for (int i = 0; i < panels; i++) {
Panel* panel = (Panel*) Vector_get(this->panels, i);
diff --git a/htop.c b/htop.c
index aee07c08..01393e61 100644
--- a/htop.c
+++ b/htop.c
@@ -24,6 +24,7 @@ in the source distribution for its full text.
#include "AffinityPanel.h"
#include "IOPriorityPanel.h"
#include "IncSet.h"
+#include "htop.h"
#include <unistd.h>
#include <math.h>
@@ -40,7 +41,32 @@ in the source distribution for its full text.
//#link m
-#define COPYRIGHT "(C) 2004-2012 Hisham Muhammad"
+#define COPYRIGHT "(C) 2004-2014 Hisham Muhammad"
+
+/*{
+
+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_ {
+ IncSet* inc;
+ Settings* settings;
+ UsersTable* ut;
+} State;
+
+typedef bool(*ForeachProcessFn)(Process*, size_t);
+
+}*/
static void printVersionFlag() {
fputs("htop " VERSION " - " COPYRIGHT "\n"
@@ -185,8 +211,6 @@ static void Setup_run(Settings* settings, const Header* header) {
ScreenManager_delete(scr);
}
-typedef bool(*ForeachProcessFn)(Process*, size_t);
-
static bool foreachProcess(Panel* panel, ForeachProcessFn fn, int arg, bool* wasAnyTagged) {
bool ok = true;
bool anyTagged = false;
@@ -222,7 +246,8 @@ static int selectedPid(Panel* panel) {
return -1;
}
-static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) {
+static Object* pickFromVector(Panel* panel, Panel* list, int x, const char** keyLabels, Header* header) {
+ int y = panel->y;
const char* fuKeys[] = {"Enter", "Esc", NULL};
int fuEvents[] = {13, 27};
ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false);
@@ -244,7 +269,6 @@ static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const cha
ScreenManager_delete(scr);
Panel_move(panel, 0, y);
Panel_resize(panel, COLS, LINES-y-1);
- FunctionBar_draw(prevBar, NULL);
if (panelFocus == list && ch == 13) {
Process* selected = (Process*)Panel_getSelected(panel);
if (selected && selected->pid == pid)
@@ -271,28 +295,6 @@ static bool setUserOnly(const char* userName, bool* userOnly, uid_t* userId) {
return false;
}
-static void setTreeView(ProcessList* pl, FunctionBar* fuBar, bool mode) {
- if (mode) {
- FunctionBar_setLabel(fuBar, KEY_F(5), "Sorted");
- FunctionBar_setLabel(fuBar, KEY_F(6), "Collap");
- } else {
- FunctionBar_setLabel(fuBar, KEY_F(5), "Tree ");
- FunctionBar_setLabel(fuBar, KEY_F(6), "SortBy");
- }
- if (mode != pl->treeView) {
- FunctionBar_draw(fuBar, NULL);
- }
- pl->treeView = mode;
-}
-
-static inline void setSortKey(ProcessList* pl, FunctionBar* fuBar, ProcessField sortKey, Panel* panel, Settings* settings) {
- pl->sortKey = sortKey;
- pl->direction = 1;
- setTreeView(pl, fuBar, false);
- settings->changed = true;
- ProcessList_printHeader(pl, Panel_getHeader(panel));
-}
-
static const char* getMainPanelValue(Panel* panel, int i) {
Process* p = (Process*) Panel_get(panel, i);
if (p)
@@ -318,7 +320,15 @@ static bool expandCollapse(Panel* panel) {
return true;
}
-void sortBy(Panel* panel, ProcessList* pl, Settings* settings, int headerHeight, FunctionBar* defaultBar, Header* header) {
+static inline Htop_Reaction setSortKey(ProcessList* pl, ProcessField sortKey) {
+ pl->sortKey = sortKey;
+ pl->direction = 1;
+ pl->treeView = false;
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction sortBy(Panel* panel, ProcessList* pl, Header* header) {
+ Htop_Reaction reaction = HTOP_OK;
Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem));
Panel_setHeader(sortPanel, "Sort by");
const char* fuFunctions[] = {"Sort ", "Cancel ", NULL};
@@ -330,14 +340,12 @@ void sortBy(Panel* panel, ProcessList* pl, Settings* settings, int headerHeight,
Panel_setSelected(sortPanel, i);
free(name);
}
- ListItem* field = (ListItem*) pickFromVector(panel, sortPanel, 15, headerHeight, fuFunctions, defaultBar, header);
+ ListItem* field = (ListItem*) pickFromVector(panel, sortPanel, 15, fuFunctions, header);
if (field) {
- settings->changed = true;
- setSortKey(pl, defaultBar, field->key, panel, settings);
- } else {
- ProcessList_printHeader(pl, Panel_getHeader(panel));
+ reaction |= setSortKey(pl, field->key);
}
Object_delete(sortPanel);
+ return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
static void millisleep(unsigned long millisec) {
@@ -350,6 +358,307 @@ static void millisleep(unsigned long millisec) {
}
}
+// ----------------------------------------
+
+static Htop_Reaction actionResize(Panel* panel) {
+ Panel_resize(panel, COLS, LINES-(panel->y)-1);
+ return HTOP_REDRAW_BAR;
+}
+
+static Htop_Reaction actionSortByMemory(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ return setSortKey(pl, PERCENT_MEM);
+}
+
+static Htop_Reaction actionSortByCPU(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ return setSortKey(pl, PERCENT_CPU);
+}
+
+static Htop_Reaction actionSortByTime(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ return setSortKey(pl, TIME);
+}
+
+static Htop_Reaction actionToggleKernelThreads(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ pl->hideKernelThreads = !pl->hideKernelThreads;
+ return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS;
+}
+
+static Htop_Reaction actionToggleUserlandThreads(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ pl->hideUserlandThreads = !pl->hideUserlandThreads;
+ pl->hideThreads = pl->hideUserlandThreads;
+ return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS;
+}
+
+static Htop_Reaction actionToggleTreeView(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ pl->treeView = !pl->treeView;
+ if (pl->treeView) pl->direction = 1;
+ ProcessList_expandTree(pl);
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionIncFilter(Panel* panel, ProcessList* pl, Header* header, State* state) {
+ (void) panel, (void) pl, (void) header;
+ IncSet_activate(state->inc, INC_FILTER);
+ return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
+}
+
+static Htop_Reaction actionIncSearch(Panel* panel, ProcessList* pl, Header* header, State* state) {
+ (void) panel, (void) pl, (void) header;
+ IncSet_activate(state->inc, INC_SEARCH);
+ return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
+}
+
+static Htop_Reaction actionHigherPriority(Panel* panel) {
+ bool changed = changePriority(panel, -1);
+ return changed ? HTOP_REFRESH : HTOP_OK;
+}
+
+static Htop_Reaction actionLowerPriority(Panel* panel) {
+ bool changed = changePriority(panel, 1);
+ return changed ? HTOP_REFRESH : HTOP_OK;
+}
+
+static Htop_Reaction actionInvertSortOrder(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ ProcessList_invertSortOrder(pl);
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
+}
+
+static Htop_Reaction actionSetIOPriority(Panel* panel, ProcessList* pl, Header* header) {
+ (void) panel, (void) pl;
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ IOPriority ioprio = p->ioPriority;
+ Panel* ioprioPanel = IOPriorityPanel_new(ioprio);
+ const char* fuFunctions[] = {"Set ", "Cancel ", NULL};
+ void* set = pickFromVector(panel, ioprioPanel, 21, fuFunctions, header);
+ if (set) {
+ IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel);
+ bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setIOPriority, (size_t) ioprio, NULL);
+ if (!ok)
+ beep();
+ }
+ Panel_delete((Object*)ioprioPanel);
+ return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionSetSortColumn(Panel* panel, ProcessList* pl, Header* header) {
+ return sortBy(panel, pl, header);
+}
+
+static Htop_Reaction actionExpandOrCollapse(Panel* panel) {
+ bool changed = expandCollapse(panel);
+ return changed ? HTOP_RECALCULATE : HTOP_OK;
+}
+
+static Htop_Reaction actionExpandCollapseOrSortColumn(Panel* panel, ProcessList* pl, Header* header) {
+ return pl->treeView ? actionExpandOrCollapse(panel) : actionSetSortColumn(panel, pl, header);
+}
+
+static Htop_Reaction actionQuit() {
+ return HTOP_QUIT;
+}
+
+static Htop_Reaction actionSetAffinity(Panel* panel, ProcessList* pl, Header* header) {
+ if (pl->cpuCount == 1)
+ return HTOP_OK;
+#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ Affinity* affinity = Process_getAffinity(p);
+ if (!affinity) return HTOP_OK;
+ Panel* affinityPanel = AffinityPanel_new(pl, affinity);
+ Affinity_delete(affinity);
+
+ const char* fuFunctions[] = {"Set ", "Cancel ", NULL};
+ void* set = pickFromVector(panel, affinityPanel, 15, fuFunctions, header);
+ if (set) {
+ Affinity* affinity = AffinityPanel_getAffinity(affinityPanel);
+ bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL);
+ if (!ok) beep();
+ Affinity_delete(affinity);
+ }
+ Panel_delete((Object*)affinityPanel);
+#endif
+ return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionKill(Panel* panel, ProcessList* pl, Header* header) {
+ (void) pl;
+ Panel* signalsPanel = (Panel*) SignalsPanel_new();
+ const char* fuFunctions[] = {"Send ", "Cancel ", NULL};
+ ListItem* sgn = (ListItem*) pickFromVector(panel, signalsPanel, 15, fuFunctions, header);
+ if (sgn) {
+ if (sgn->key != 0) {
+ Panel_setHeader(panel, "Sending...");
+ Panel_draw(panel, true);
+ refresh();
+ foreachProcess(panel, (ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL);
+ napms(500);
+ }
+ }
+ Panel_delete((Object*)signalsPanel);
+ return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionFilterByUser(Panel* panel, ProcessList* pl, Header* header, State* state) {
+ Panel* usersPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem));
+ Panel_setHeader(usersPanel, "Show processes of:");
+ UsersTable_foreach(state->ut, addUserToVector, usersPanel);
+ Vector_insertionSort(usersPanel->items);
+ ListItem* allUsers = ListItem_new("All users", -1);
+ Panel_insert(usersPanel, 0, (Object*) allUsers);
+ const char* fuFunctions[] = {"Show ", "Cancel ", NULL};
+ ListItem* picked = (ListItem*) pickFromVector(panel, usersPanel, 20, fuFunctions, header);
+ if (picked) {
+ if (picked == allUsers) {
+ pl->userOnly = false;
+ } else {
+ setUserOnly(ListItem_getRef(picked), &(pl->userOnly), &(pl->userId));
+ }
+ }
+ Panel_delete((Object*)usersPanel);
+ return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionFollow() {
+ return HTOP_KEEP_FOLLOWING;
+}
+
+static Htop_Reaction actionSetup(Panel* panel, ProcessList* pl, Header* header, State* state) {
+ (void) pl;
+ Setup_run(state->settings, header);
+ // TODO: shouldn't need this, colors should be dynamic
+ int headerHeight = Header_calculateHeight(header);
+ Panel_move(panel, 0, headerHeight);
+ Panel_resize(panel, COLS, LINES-headerHeight-1);
+ return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
+}
+
+static Htop_Reaction actionLsof(Panel* panel) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ OpenFilesScreen* ts = OpenFilesScreen_new(p);
+ OpenFilesScreen_run(ts);
+ OpenFilesScreen_delete(ts);
+ clear();
+ CRT_enableDelay();
+ return HTOP_REFRESH | HTOP_REDRAW_BAR;
+}
+
+static Htop_Reaction actionStrace(Panel* panel) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ TraceScreen* ts = TraceScreen_new(p);
+ TraceScreen_run(ts);
+ TraceScreen_delete(ts);
+ clear();
+ CRT_enableDelay();
+ return HTOP_REFRESH | HTOP_REDRAW_BAR;
+}
+
+static Htop_Reaction actionTag(Panel* panel) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ Process_toggleTag(p);
+ Panel_onKey(panel, KEY_DOWN);
+ return HTOP_OK;
+}
+
+static Htop_Reaction actionRedraw() {
+ clear();
+ return HTOP_REFRESH | HTOP_REDRAW_BAR;
+}
+
+static Htop_Reaction actionHelp(Panel* panel, ProcessList* pl) {
+ (void) panel;
+ showHelp(pl);
+ return HTOP_RECALCULATE | HTOP_REDRAW_BAR;
+}
+
+static Htop_Reaction actionUntagAll(Panel* panel) {
+ for (int i = 0; i < Panel_size(panel); i++) {
+ Process* p = (Process*) Panel_get(panel, i);
+ p->tag = false;
+ }
+ return HTOP_REFRESH;
+}
+
+static Htop_Reaction actionTagAllChildren(Panel* panel) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return HTOP_OK;
+ tagAllChildren(panel, p);
+ return HTOP_OK;
+}
+
+void setBindings(Htop_Action* keys) {
+ keys[KEY_RESIZE] = actionResize;
+ keys['M'] = actionSortByMemory;
+ keys['T'] = actionSortByTime;
+ keys['P'] = actionSortByCPU;
+ keys['H'] = actionToggleUserlandThreads;
+ keys['K'] = actionToggleKernelThreads;
+ keys['t'] = actionToggleTreeView;
+ keys[KEY_F(5)] = actionToggleTreeView;
+ keys[KEY_F(4)] = actionIncFilter;
+ keys['\\'] = actionIncFilter;
+ keys[KEY_F(3)] = actionIncSearch;
+ keys['/'] = actionIncSearch;
+
+ keys[']'] = actionHigherPriority;
+ keys[KEY_F(7)] = actionHigherPriority;
+ keys['['] = actionLowerPriority;
+ keys[KEY_F(8)] = actionLowerPriority;
+ keys['I'] = actionInvertSortOrder;
+ keys['i'] = actionSetIOPriority;
+ keys[KEY_F(6)] = actionExpandCollapseOrSortColumn;
+ keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
+ keys['<'] = actionSetSortColumn;
+ keys[','] = actionSetSortColumn;
+ keys['>'] = actionSetSortColumn;
+ keys['.'] = actionSetSortColumn;
+ keys[KEY_F(10)] = actionQuit;
+ keys['q'] = actionQuit;
+ keys['a'] = actionSetAffinity;
+ keys[KEY_F(9)] = actionKill;
+ keys['k'] = actionKill;
+ keys['+'] = actionExpandOrCollapse;
+ keys['='] = actionExpandOrCollapse;
+ keys['-'] = actionExpandOrCollapse;
+ keys['u'] = actionFilterByUser;
+ keys['F'] = actionFollow;
+ keys['S'] = actionSetup;
+ keys['C'] = actionSetup;
+ keys[KEY_F(2)] = actionSetup;
+ keys['l'] = actionLsof;
+ keys['s'] = actionStrace;
+ keys[' '] = actionTag;
+ keys['\014'] = actionRedraw; // Ctrl+L
+ keys[KEY_F(1)] = actionHelp;
+ keys['h'] = actionHelp;
+ keys['?'] = actionHelp;
+ keys['U'] = actionUntagAll;
+ keys['c'] = actionTagAllChildren;
+}
+
+// ----------------------------------------
+
+
+static void updateTreeFunctions(FunctionBar* fuBar, bool mode) {
+ if (mode) {
+ FunctionBar_setLabel(fuBar, KEY_F(5), "Sorted");
+ FunctionBar_setLabel(fuBar, KEY_F(6), "Collap");
+ } else {
+ FunctionBar_setLabel(fuBar, KEY_F(5), "Tree ");
+ FunctionBar_setLabel(fuBar, KEY_F(6), "SortBy");
+ }
+}
+
int main(int argc, char** argv) {
int delay = -1;
@@ -453,11 +762,11 @@ int main(int argc, char** argv) {
exit(1);
}
- int quit = 0;
- int refreshTimeout = 0;
- int resetRefreshTimeout = 5;
+ bool quit = false;
+ int sortTimeout = 0;
+ int resetSortTimeout = 5;
bool doRefresh = true;
- bool doRecalculate = false;
+ bool forceRecalculate = false;
Settings* settings;
ProcessList* pl = NULL;
@@ -478,6 +787,8 @@ int main(int argc, char** argv) {
#endif
pl = ProcessList_new(ut, pidWhiteList);
+ pl->userOnly = userOnly;
+ pl->userId = userId;
Process_getMaxPid();
Header* header = Header_new(pl);
@@ -496,18 +807,17 @@ int main(int argc, char** argv) {
ProcessList_setPanel(pl, panel);
FunctionBar* defaultBar = FunctionBar_new(defaultFunctions, NULL, NULL);
- setTreeView(pl, defaultBar, pl->treeView);
+ updateTreeFunctions(defaultBar, pl->treeView);
if (sortKey > 0) {
pl->sortKey = sortKey;
- setTreeView(pl, defaultBar, false);
+ pl->treeView = false;
pl->direction = 1;
}
ProcessList_printHeader(pl, Panel_getHeader(panel));
IncSet* inc = IncSet_new(defaultBar);
-
ProcessList_scan(pl);
millisleep(75);
ProcessList_scan(pl);
@@ -523,31 +833,40 @@ int main(int argc, char** argv) {
int ch = ERR;
int closeTimeout = 0;
- bool idle = false;
+ bool drawPanel = true;
bool collapsed = false;
+ Htop_Action keys[KEY_MAX] = { NULL };
+ setBindings(keys);
+
+ State state = {
+ .inc = inc,
+ .settings = settings,
+ .ut = ut,
+ };
+
while (!quit) {
gettimeofday(&tv, NULL);
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
- bool recalculate = (newTime - oldTime > settings->delay);
- if (newTime < oldTime) recalculate = true; // clock was adjusted?
+ bool timeToRecalculate = (newTime - oldTime > settings->delay);
+ if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
int following = follow ? selectedPid(panel) : -1;
- if (recalculate) {
+ if (timeToRecalculate) {
Header_draw(header);
oldTime = newTime;
}
if (doRefresh) {
- if (recalculate || doRecalculate) {
+ if (timeToRecalculate || forceRecalculate) {
ProcessList_scan(pl);
- doRecalculate = false;
+ forceRecalculate = false;
}
- if (refreshTimeout == 0 || pl->treeView) {
+ if (sortTimeout == 0 || pl->treeView) {
ProcessList_sort(pl);
- refreshTimeout = 1;
+ sortTimeout = 1;
}
- ProcessList_rebuildPanel(pl, true, following, userOnly, userId, IncSet_filter(inc));
- idle = false;
+ ProcessList_rebuildPanel(pl, true, following, IncSet_filter(inc));
+ drawPanel = true;
}
doRefresh = true;
@@ -563,9 +882,11 @@ int main(int argc, char** argv) {
}
collapsed = !p->showChildren;
}
+ } else {
+ collapsed = false;
}
- if (!idle) {
+ if (drawPanel) {
Panel_draw(panel, true);
}
@@ -576,18 +897,20 @@ int main(int argc, char** argv) {
if (ch == ERR) {
if (!inc->active)
- refreshTimeout--;
- if (prev == ch && !recalculate) {
+ sortTimeout--;
+ if (prev == ch && !timeToRecalculate) {
closeTimeout++;
if (closeTimeout == 100) {
break;
}
} else
closeTimeout = 0;
- idle = true;
+ drawPanel = false;
continue;
}
- idle = false;
+ drawPanel = true;
+
+ Htop_Reaction reaction = HTOP_OK;
if (ch == KEY_MOUSE) {
MEVENT mevent;
@@ -599,18 +922,17 @@ int main(int argc, char** argv) {
ProcessField field = ProcessList_keyAt(pl, x);
if (field == pl->sortKey) {
ProcessList_invertSortOrder(pl);
- setTreeView(pl, defaultBar, false);
+ pl->treeView = false;
+ reaction |= HTOP_REDRAW_BAR;
} else {
- setSortKey(pl, defaultBar, field, panel, settings);
+ reaction |= setSortKey(pl, field);
}
- refreshTimeout = 0;
- continue;
+ sortTimeout = 0;
+ ch = ERR;
} else if (mevent.y >= panel->y + 1 && mevent.y < LINES - 1) {
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
- doRefresh = false;
- refreshTimeout = resetRefreshTimeout;
follow = true;
- continue;
+ ch = ERR;
} if (mevent.y == LINES - 1) {
ch = FunctionBar_synthesizeEvent(inc->bar, mevent.x);
}
@@ -650,298 +972,38 @@ int main(int argc, char** argv) {
acc = 0;
}
- switch (ch) {
- case KEY_RESIZE:
- Panel_resize(panel, COLS, LINES-headerHeight-1);
- IncSet_drawBar(inc);
- break;
- case 'M':
- {
- refreshTimeout = 0;
- setSortKey(pl, defaultBar, PERCENT_MEM, panel, settings);
- break;
- }
- case 'T':
- {
- refreshTimeout = 0;
- setSortKey(pl, defaultBar, TIME, panel, settings);
- break;
- }
- case 'c':
- {
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- tagAllChildren(panel, p);
- break;
- }
- case 'U':
- {
- for (int i = 0; i < Panel_size(panel); i++) {
- Process* p = (Process*) Panel_get(panel, i);
- p->tag = false;
- }
- doRefresh = true;
- break;
- }
- case 'P':
- {
- refreshTimeout = 0;
- setSortKey(pl, defaultBar, PERCENT_CPU, panel, settings);
- break;
- }
- case KEY_F(1):
- case 'h':
- case '?':
- {
- showHelp(pl);
- FunctionBar_draw(defaultBar, NULL);
- recalculate = true;
- refreshTimeout = 0;
- break;
- }
- case '\014': // Ctrl+L
- {
- clear();
- FunctionBar_draw(defaultBar, NULL);
- refreshTimeout = 0;
- break;
- }
- case ' ':
- {
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- Process_toggleTag(p);
- Panel_onKey(panel, KEY_DOWN);
- break;
- }
- case 's':
- {
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- TraceScreen* ts = TraceScreen_new(p);
- TraceScreen_run(ts);
- TraceScreen_delete(ts);
- clear();
- FunctionBar_draw(defaultBar, NULL);
- refreshTimeout = 0;
- CRT_enableDelay();
- break;
- }
- case 'l':
- {
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- OpenFilesScreen* ts = OpenFilesScreen_new(p);
- OpenFilesScreen_run(ts);
- OpenFilesScreen_delete(ts);
- clear();
- FunctionBar_draw(defaultBar, NULL);
- refreshTimeout = 0;
- CRT_enableDelay();
- break;
- }
- case 'S':
- case 'C':
- case KEY_F(2):
- {
- Setup_run(settings, header);
- // TODO: shouldn't need this, colors should be dynamic
- ProcessList_printHeader(pl, Panel_getHeader(panel));
- headerHeight = Header_calculateHeight(header);
- Panel_move(panel, 0, headerHeight);
- Panel_resize(panel, COLS, LINES-headerHeight-1);
- FunctionBar_draw(defaultBar, NULL);
- refreshTimeout = 0;
- break;
- }
- case 'F':
- {
- follow = true;
- continue;
- }
- case 'u':
- {
- Panel* usersPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem));
- Panel_setHeader(usersPanel, "Show processes of:");
- UsersTable_foreach(ut, addUserToVector, usersPanel);
- Vector_insertionSort(usersPanel->items);
- ListItem* allUsers = ListItem_new("All users", -1);
- Panel_insert(usersPanel, 0, (Object*) allUsers);
- const char* fuFunctions[] = {"Show ", "Cancel ", NULL};
- ListItem* picked = (ListItem*) pickFromVector(panel, usersPanel, 20, headerHeight, fuFunctions, defaultBar, header);
- if (picked) {
- if (picked == allUsers) {
- userOnly = false;
- } else {
- setUserOnly(ListItem_getRef(picked), &userOnly, &userId);
- }
- }
- Panel_delete((Object*)usersPanel);
- break;
- }
- case '+':
- case '=':
- case '-':
- {
- if (expandCollapse(panel)) {
- doRecalculate = true;
- refreshTimeout = 0;
- }
- break;
- }
- case KEY_F(9):
- case 'k':
- {
- Panel* signalsPanel = (Panel*) SignalsPanel_new();
- const char* fuFunctions[] = {"Send ", "Cancel ", NULL};
- ListItem* sgn = (ListItem*) pickFromVector(panel, signalsPanel, 15, headerHeight, fuFunctions, defaultBar, header);
- if (sgn) {
- if (sgn->key != 0) {
- Panel_setHeader(panel, "Sending...");
- Panel_draw(panel, true);
- refresh();
- foreachProcess(panel, (ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL);
- napms(500);
- }
- }
- ProcessList_printHeader(pl, Panel_getHeader(panel));
- Panel_delete((Object*)signalsPanel);
- refreshTimeout = 0;
- break;
+ if(ch != ERR && keys[ch]) {
+ reaction |= (keys[ch])(panel, pl, header, &state);
+ } else {
+ doRefresh = false;
+ sortTimeout = resetSortTimeout;
+ Panel_onKey(panel, ch);
}
-#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
- case 'a':
- {
- if (pl->cpuCount == 1)
- break;
+
+ // Reaction handlers:
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- Affinity* affinity = Process_getAffinity(p);
- if (!affinity) break;
- Panel* affinityPanel = AffinityPanel_new(pl, affinity);
- Affinity_delete(affinity);
-
- const char* fuFunctions[] = {"Set ", "Cancel ", NULL};
- void* set = pickFromVector(panel, affinityPanel, 15, headerHeight, fuFunctions, defaultBar, header);
- if (set) {
- Affinity* affinity = AffinityPanel_getAffinity(affinityPanel);
- bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL);
- if (!ok) beep();
- Affinity_delete(affinity);
- }
- Panel_delete((Object*)affinityPanel);
- ProcessList_printHeader(pl, Panel_getHeader(panel));
- refreshTimeout = 0;
- break;
- }
-#endif
- case KEY_F(10):
- case 'q':
- quit = 1;
- break;
- case '<':
- case ',':
- case '>':
- case '.':
- {
- sortBy(panel, pl, settings, headerHeight, defaultBar, header);
- refreshTimeout = 0;
- break;
- }
- case KEY_F(18):
- case KEY_F(6):
- {
- if (pl->treeView) {
- if (expandCollapse(panel)) {
- doRecalculate = true;
- refreshTimeout = 0;
- }
- } else {
- sortBy(panel, pl, settings, headerHeight, defaultBar, header);
- refreshTimeout = 0;
- }
- break;
+ if (reaction & HTOP_REDRAW_BAR) {
+ updateTreeFunctions(defaultBar, pl->treeView);
+ IncSet_drawBar(inc);
}
- case 'i':
- {
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- IOPriority ioprio = p->ioPriority;
- Panel* ioprioPanel = IOPriorityPanel_new(ioprio);
- const char* fuFunctions[] = {"Set ", "Cancel ", NULL};
- void* set = pickFromVector(panel, ioprioPanel, 21, headerHeight, fuFunctions, defaultBar, header);
- if (set) {
- IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel);
- bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setIOPriority, (size_t) ioprio, NULL);
- if (!ok)
- beep();
- }
- Panel_delete((Object*)ioprioPanel);
+ if (reaction & HTOP_UPDATE_PANELHDR) {
ProcessList_printHeader(pl, Panel_getHeader(panel));
- refreshTimeout = 0;
- break;
}
- case 'I':
- {
- refreshTimeout = 0;
- settings->changed = true;
- ProcessList_invertSortOrder(pl);
- break;
- }
- case KEY_F(8):
- case '[':
- {
- doRefresh = changePriority(panel, 1);
- break;
- }
- case KEY_F(7):
- case ']':
- {
- doRefresh = changePriority(panel, -1);
- break;
- }
- case KEY_F(3):
- case '/':
- IncSet_activate(inc, INC_SEARCH);
- break;
- case KEY_F(4):
- case '\\':
- IncSet_activate(inc, INC_FILTER);
- refreshTimeout = 0;
+ if (reaction & HTOP_REFRESH) {
doRefresh = true;
- continue;
- case 't':
- case KEY_F(5):
- refreshTimeout = 0;
- collapsed = false;
- setTreeView(pl, defaultBar, !pl->treeView);
- if (pl->treeView) pl->direction = 1;
- ProcessList_printHeader(pl, Panel_getHeader(panel));
- ProcessList_expandTree(pl);
- settings->changed = true;
- if (following != -1) continue;
- break;
- case 'H':
- doRecalculate = true;
- refreshTimeout = 0;
- pl->hideUserlandThreads = !pl->hideUserlandThreads;
- pl->hideThreads = pl->hideUserlandThreads;
- settings->changed = true;
- break;
- case 'K':
- doRecalculate = true;
- refreshTimeout = 0;
- pl->hideKernelThreads = !pl->hideKernelThreads;
+ sortTimeout = 0;
+ }
+ if (reaction & HTOP_RECALCULATE) {
+ forceRecalculate = true;
+ sortTimeout = 0;
+ }
+ if (reaction & HTOP_SAVE_SETTINGS) {
settings->changed = true;
- break;
- default:
- doRefresh = false;
- refreshTimeout = resetRefreshTimeout;
- Panel_onKey(panel, ch);
- break;
}
- follow = false;
+ if (reaction & HTOP_QUIT) {
+ quit = true;
+ }
+ follow = (reaction & HTOP_KEEP_FOLLOWING);
}
attron(CRT_colors[RESET_COLOR]);
mvhline(LINES-1, 0, ' ', COLS);
@@ -953,11 +1015,14 @@ int main(int argc, char** argv) {
Settings_write(settings);
Header_delete(header);
ProcessList_delete(pl);
- IncSet_delete(inc);
+
FunctionBar_delete((Object*)defaultBar);
Panel_delete((Object*)panel);
+
+ IncSet_delete(inc);
UsersTable_delete(ut);
Settings_delete(settings);
+
if(pidWhiteList) {
Hashtable_delete(pidWhiteList);
}
diff --git a/htop.h b/htop.h
index 354a2f99..a1369431 100644
--- a/htop.h
+++ b/htop.h
@@ -11,11 +11,36 @@ in the source distribution for its full text.
//#link m
-#define COPYRIGHT "(C) 2004-2012 Hisham Muhammad"
+#define COPYRIGHT "(C) 2004-2014 Hisham Muhammad"
+
+
+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_ {
+ IncSet* inc;
+ Settings* settings;
+ UsersTable* ut;
+} State;
typedef bool(*ForeachProcessFn)(Process*, size_t);
-void sortBy(Panel* panel, ProcessList* pl, Settings* settings, int headerHeight, FunctionBar* defaultBar, Header* header);
+
+// ----------------------------------------
+
+void setBindings(Htop_Action* keys);
+
+// ----------------------------------------
int main(int argc, char** argv);

© 2014-2024 Faster IT GmbH | imprint | privacy policy