htop.c 29.7 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop - htop.c
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
9
10
11
12
13
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#define _GNU_SOURCE
#include <unistd.h>
#include <math.h>
#include <sys/param.h>
#include <ctype.h>
#include <stdbool.h>
14
#include <locale.h>
15
#include <getopt.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
16
17
18

#include "ProcessList.h"
#include "CRT.h"
19
#include "Panel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
20
21
22
23
24
25
#include "UsersTable.h"
#include "RichString.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "FunctionBar.h"
#include "ListItem.h"
26
27
#include "CategoriesPanel.h"
#include "SignalsPanel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
28
#include "TraceScreen.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
29
#include "OpenFilesScreen.h"
30
#include "AffinityPanel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
31

Hisham Muhammad's avatar
Hisham Muhammad committed
32
#include "config.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
33
34
35
36
37
38
#include "debug.h"

//#link m

#define INCSEARCH_MAX 40

39
#define COPYRIGHT "(C) 2004-2011 Hisham Muhammad"
40

41
static void printVersionFlag() {
42
43
44
   fputs("htop " VERSION " - " COPYRIGHT "\n"
         "Released under the GNU GPL.\n\n",
         stdout);
Hisham Muhammad's avatar
Hisham Muhammad committed
45
46
47
   exit(0);
}

48
static void printHelpFlag() {
49
50
51
52
53
54
55
56
57
58
59
60
61
   fputs("htop " VERSION " - " COPYRIGHT "\n"
         "Released under the GNU GPL.\n\n"
         "-C --no-color         Use a monochrome color scheme\n"
         "-d --delay=DELAY      Set the delay between updates, in tenths of seconds\n"
         "-h --help             Print this help screen\n"
         "-s --sort-key=COLUMN  Sort by COLUMN (try --sort-key=help for a list)\n"
         "-u --user=USERNAME    Show only processes of a given user\n"
         "-v --version          Print version info\n"
         "\n"
         "Long options may be passed with a single dash.\n\n"
         "Press F1 inside htop for online help.\n"
         "See 'man htop' for more information.\n",
         stdout);
Hisham Muhammad's avatar
Hisham Muhammad committed
62
63
64
   exit(0);
}

65
static void showHelp(ProcessList* pl) {
Hisham Muhammad's avatar
Hisham Muhammad committed
66
67
   clear();
   attrset(CRT_colors[HELP_BOLD]);
68
69
70
71

   for (int i = 0; i < LINES-1; i++)
      mvhline(i, 0, ' ', COLS);

72
   mvaddstr(0, 0, "htop " VERSION " - " COPYRIGHT);
Hisham Muhammad's avatar
Hisham Muhammad committed
73
74
75
76
77
78
   mvaddstr(1, 0, "Released under the GNU GPL. See 'man' page for more info.");

   attrset(CRT_colors[DEFAULT_COLOR]);
   mvaddstr(3, 0, "CPU usage bar: ");
   #define addattrstr(a,s) attrset(a);addstr(s)
   addattrstr(CRT_colors[BAR_BORDER], "[");
79
   if (pl->detailedCPUTime) {
80
81
82
83
      addattrstr(CRT_colors[CPU_NICE], "low"); addstr("/");
      addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
      addattrstr(CRT_colors[CPU_KERNEL], "kernel"); addstr("/");
      addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/");
84
      addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/");
85
86
87
      addattrstr(CRT_colors[CPU_IOWAIT], "io-wait"); addstr("/");
      addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/");
      addattrstr(CRT_colors[CPU_GUEST], "guest");
88
89
90
91
      addattrstr(CRT_colors[BAR_SHADOW], " used%");
   } else {
      addattrstr(CRT_colors[CPU_NICE], "low-priority"); addstr("/");
      addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
92
93
94
      addattrstr(CRT_colors[CPU_KERNEL], "kernel"); addstr("/");
      addattrstr(CRT_colors[CPU_STEAL], "virtualiz");
      addattrstr(CRT_colors[BAR_SHADOW], "               used%");
95
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
96
97
98
99
100
101
102
   addattrstr(CRT_colors[BAR_BORDER], "]");
   attrset(CRT_colors[DEFAULT_COLOR]);
   mvaddstr(4, 0, "Memory bar:    ");
   addattrstr(CRT_colors[BAR_BORDER], "[");
   addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/");
   addattrstr(CRT_colors[MEMORY_BUFFERS], "buffers"); addstr("/");
   addattrstr(CRT_colors[MEMORY_CACHE], "cache");
103
   addattrstr(CRT_colors[BAR_SHADOW], "                            used/total");
Hisham Muhammad's avatar
Hisham Muhammad committed
104
105
106
107
108
   addattrstr(CRT_colors[BAR_BORDER], "]");
   attrset(CRT_colors[DEFAULT_COLOR]);
   mvaddstr(5, 0, "Swap bar:      ");
   addattrstr(CRT_colors[BAR_BORDER], "[");
   addattrstr(CRT_colors[SWAP], "used");
109
   addattrstr(CRT_colors[BAR_SHADOW], "                                          used/total");
Hisham Muhammad's avatar
Hisham Muhammad committed
110
111
   addattrstr(CRT_colors[BAR_BORDER], "]");
   attrset(CRT_colors[DEFAULT_COLOR]);
112
   mvaddstr(6,0, "Type and layout of header meters are configurable in the setup screen.");
113
114
115
116
   if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
      mvaddstr(7, 0, "In monochrome, meters are displayed through different chars, in order: |#*@$%&");
   }
   mvaddstr( 8, 0, " Status: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep");
117
118
119
   mvaddstr( 9, 0, " Arrows: scroll process list             F5 t: tree view");
   mvaddstr(10, 0, " Digits: incremental PID search             u: show processes of a single user");
   mvaddstr(11, 0, "   F3 /: incremental name search            H: hide/show user threads");
Hisham Muhammad's avatar
Hisham Muhammad committed
120
   mvaddstr(12, 0, "   F4 \\: incremental name filtering         K: hide/show kernel threads");
121
   mvaddstr(13, 0, "  Space: tag processes                      F: cursor follows process");
Hisham Muhammad's avatar
Hisham Muhammad committed
122
   mvaddstr(14, 0, "      U: untag all processes              + -: expand/collapse tree");
123
   mvaddstr(15, 0, "   F9 k: kill process/tagged processes      P: sort by CPU%");
Hisham Muhammad's avatar
Hisham Muhammad committed
124
125
   mvaddstr(16, 0, "   ] F7: higher priority (root only)        M: sort by MEM%");
   mvaddstr(17, 0, "   [ F8: lower priority (+ nice)            T: sort by TIME");
126
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
127
   if (pl->cpuCount > 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
128
      mvaddstr(18, 0, "      a: set CPU affinity                   I: invert sort order");
129
   else
Hisham Muhammad's avatar
Hisham Muhammad committed
130
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
131
      mvaddstr(18, 0, "                                            I: invert sort order");
132
   mvaddstr(19, 0, "   F2 S: setup                           F6 >: select sort column");
Hisham Muhammad's avatar
Hisham Muhammad committed
133
   mvaddstr(20, 0, "   F1 h: show this help screen              l: list open files with lsof");
134
   mvaddstr(21, 0, "  F10 q: quit                               s: trace syscalls with strace");
Hisham Muhammad's avatar
Hisham Muhammad committed
135
136

   attrset(CRT_colors[HELP_BOLD]);
137
138
139
   mvaddstr( 9, 0, " Arrows"); mvaddstr( 9,40, " F5 t");
   mvaddstr(10, 0, " Digits"); mvaddstr(10,40, "    u");
   mvaddstr(11, 0, "   F3 /"); mvaddstr(11,40, "    H");
Hisham Muhammad's avatar
Hisham Muhammad committed
140
   mvaddstr(12, 0, "   F4 \\"); mvaddstr(12,40, "    K");
141
   mvaddstr(13, 0, "  Space"); mvaddstr(13,40, "    F");
Hisham Muhammad's avatar
Hisham Muhammad committed
142
   mvaddstr(14, 0, "      U"); mvaddstr(14,40, "  + -");
143
   mvaddstr(15, 0, "   F9 k"); mvaddstr(15,40, "    P");
144
145
   mvaddstr(16, 0, "   ] F7"); mvaddstr(16,40, "    M");
   mvaddstr(17, 0, "   [ F8"); mvaddstr(17,40, "    T");
146
                               mvaddstr(18,40, " F4 I");
147
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
148
   if (pl->cpuCount > 1)
149
      mvaddstr(18, 0, "      a:");
Hisham Muhammad's avatar
Hisham Muhammad committed
150
#endif
151
   mvaddstr(19, 0, "   F2 S"); mvaddstr(19,40, " F6 >");
152
   mvaddstr(20, 0, " ? F1 h"); mvaddstr(20,40, "    l");
153
   mvaddstr(21, 0, "  F10 q"); mvaddstr(21,40, "    s");
Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
156
157
158
159
160
161
162
163
   attrset(CRT_colors[DEFAULT_COLOR]);

   attrset(CRT_colors[HELP_BOLD]);
   mvaddstr(23,0, "Press any key to return.");
   attrset(CRT_colors[DEFAULT_COLOR]);
   refresh();
   CRT_readKey();
   clear();
}

Hisham Muhammad's avatar
Hisham Muhammad committed
164
static const char* CategoriesFunctions[] = {"      ", "      ", "      ", "      ", "      ", "      ", "      ", "      ", "      ", "Done  ", NULL};
165

166
167
static void Setup_run(Settings* settings, const Header* header) {
   ScreenManager* scr = ScreenManager_new(0, header->height, 0, -1, HORIZONTAL, header, true);
Hisham Muhammad's avatar
Hisham Muhammad committed
168
   CategoriesPanel* panelCategories = CategoriesPanel_new(settings, scr);
Hisham Muhammad's avatar
Hisham Muhammad committed
169
   ScreenManager_add(scr, (Panel*) panelCategories, FunctionBar_new(CategoriesFunctions, NULL, NULL), 16);
Hisham Muhammad's avatar
Hisham Muhammad committed
170
171
   CategoriesPanel_makeMetersPage(panelCategories);
   Panel* panelFocus;
Hisham Muhammad's avatar
Hisham Muhammad committed
172
   int ch;
Hisham Muhammad's avatar
Hisham Muhammad committed
173
   ScreenManager_run(scr, &panelFocus, &ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
174
175
176
   ScreenManager_delete(scr);
}

Hisham Muhammad's avatar
Hisham Muhammad committed
177
static bool changePriority(Panel* panel, int delta) {
178
   bool ok = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
179
   bool anyTagged = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
180
   for (int i = 0; i < Panel_size(panel); i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
181
      Process* p = (Process*) Panel_get(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
182
      if (p->tag) {
183
         ok = Process_setPriority(p, p->nice + delta) && ok;
Hisham Muhammad's avatar
Hisham Muhammad committed
184
185
186
187
         anyTagged = true;
      }
   }
   if (!anyTagged) {
Hisham Muhammad's avatar
Hisham Muhammad committed
188
      Process* p = (Process*) Panel_getSelected(panel);
189
      ok = Process_setPriority(p, p->nice + delta) && ok;
Hisham Muhammad's avatar
Hisham Muhammad committed
190
   }
191
192
   if (!ok)
      beep();
Hisham Muhammad's avatar
Hisham Muhammad committed
193
194
195
   return anyTagged;
}

196
static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) {
Hisham Muhammad's avatar
Hisham Muhammad committed
197
   const char* fuKeys[] = {"Enter", "Esc", NULL};
198
   int fuEvents[] = {13, 27};
199
   if (!list->eventHandler)
200
      Panel_setEventHandler(list, Panel_selectByTyping);
201
   ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false);
Hisham Muhammad's avatar
Hisham Muhammad committed
202
   ScreenManager_add(scr, list, FunctionBar_new(keyLabels, fuKeys, fuEvents), x - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
203
204
   ScreenManager_add(scr, panel, NULL, -1);
   Panel* panelFocus;
Hisham Muhammad's avatar
Hisham Muhammad committed
205
   int ch;
Hisham Muhammad's avatar
Hisham Muhammad committed
206
   ScreenManager_run(scr, &panelFocus, &ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
207
   ScreenManager_delete(scr);
Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
   Panel_move(panel, 0, y);
   Panel_resize(panel, COLS, LINES-y-1);
Hisham Muhammad's avatar
Hisham Muhammad committed
210
   FunctionBar_draw(prevBar, NULL);
Hisham Muhammad's avatar
Hisham Muhammad committed
211
   if (panelFocus == list && ch == 13) {
212
      return Panel_getSelected(list);
Hisham Muhammad's avatar
Hisham Muhammad committed
213
214
215
216
   }
   return NULL;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
217
static void addUserToVector(int key, void* userCast, void* panelCast) {
Hisham Muhammad's avatar
Hisham Muhammad committed
218
   char* user = (char*) userCast;
Hisham Muhammad's avatar
Hisham Muhammad committed
219
220
   Panel* panel = (Panel*) panelCast;
   Panel_add(panel, (Object*) ListItem_new(user, key));
Hisham Muhammad's avatar
Hisham Muhammad committed
221
222
}

223
static bool setUserOnly(const char* userName, bool* userOnly, uid_t* userId) {
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
226
227
   struct passwd* user = getpwnam(userName);
   if (user) {
      *userOnly = true;
      *userId = user->pw_uid;
228
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
229
   }
230
   return false;
Hisham Muhammad's avatar
Hisham Muhammad committed
231
232
}

233
234
235
236
237
static inline void setSortKey(ProcessList* pl, ProcessField sortKey, Panel* panel, Settings* settings) {
   pl->sortKey = sortKey;
   pl->direction = 1;
   pl->treeView = false;
   settings->changed = true;
238
   ProcessList_printHeader(pl, Panel_getHeader(panel));
239
240
}

Hisham Muhammad's avatar
Hisham Muhammad committed
241
242
243
244
245
246
247
248
249
250
251
typedef struct IncBuffer_ {
   char buffer[INCSEARCH_MAX];
   int index;
   FunctionBar* bar;
} IncBuffer;

static void IncBuffer_reset(IncBuffer* inc) {
   inc->index = 0;
   inc->buffer[0] = 0;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
252
253
254
255
256
int main(int argc, char** argv) {

   int delay = -1;
   bool userOnly = false;
   uid_t userId = 0;
257
   int usecolors = 1;
258
   TreeType treeType = TREE_TYPE_AUTO;
259
260
261
262
263
264
265
266
267
268
269
270
271

   int opt, opti=0;
   static struct option long_opts[] =
   {
      {"help",     no_argument,         0, 'h'},
      {"version",  no_argument,         0, 'v'},
      {"delay",    required_argument,   0, 'd'},
      {"sort-key", required_argument,   0, 's'},
      {"user",     required_argument,   0, 'u'},
      {"no-color", no_argument,         0, 'C'},
      {"no-colour",no_argument,         0, 'C'},
      {0,0,0,0}
   };
272
   int sortKey = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
273

274
275
276
   char *lc_ctype = getenv("LC_CTYPE");
   if(lc_ctype != NULL)
      setlocale(LC_CTYPE, lc_ctype);
277
278
   else if ((lc_ctype = getenv("LC_ALL")))
      setlocale(LC_CTYPE, lc_ctype);
279
   else
280
      setlocale(LC_CTYPE, "");
281

282
   /* Parse arguments */
283
   while ((opt = getopt_long(argc, argv, "hvCs:d:u:", long_opts, &opti))) {
284
285
286
287
288
289
290
291
292
      if (opt == EOF) break;
      switch (opt) {
         case 'h':
            printHelpFlag();
            break;
         case 'v':
            printVersionFlag();
            break;
         case 's':
Hisham Muhammad's avatar
Hisham Muhammad committed
293
            if (strcmp(optarg, "help") == 0) {
294
295
296
297
298
299
300
301
302
303
304
305
               for (int j = 1; j < LAST_PROCESSFIELD; j++)
                  printf ("%s\n", Process_fieldNames[j]);
               exit(0);
            }

            sortKey = ColumnsPanel_fieldNameToIndex(optarg);
            if (sortKey == -1) {
               fprintf(stderr, "Error: invalid column \"%s\".\n", optarg);
               exit(1);
            }
            break;
         case 'd':
306
307
308
309
310
311
312
            if (sscanf(optarg, "%d", &delay) == 1) {
               if (delay < 1) delay = 1;
               if (delay > 100) delay = 100;
            } else {
               fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg);
               exit(1);
            }
313
314
            break;
         case 'u':
315
316
317
318
            if (!setUserOnly(optarg, &userOnly, &userId)) {
               fprintf(stderr, "Error: invalid user \"%s\".\n", optarg);
               exit(1);
            }
319
320
321
322
            break;
         case 'C':
            usecolors=0;
            break;
323
324
         default:
            exit(1);
Hisham Muhammad's avatar
Hisham Muhammad committed
325
326
      }
   }
327
328


329
330
331
332
   if (access(PROCDIR, R_OK) != 0) {
      fprintf(stderr, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR);
      exit(1);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
333

Hisham Muhammad's avatar
Hisham Muhammad committed
334
   Panel* panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
335
336
337
338
   int quit = 0;
   int refreshTimeout = 0;
   int resetRefreshTimeout = 5;
   bool doRefresh = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
339
   bool doRecalculate = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
340
341
   Settings* settings;
   
Hisham Muhammad's avatar
Hisham Muhammad committed
342
   Panel* killPanel = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
343
   
Hisham Muhammad's avatar
Hisham Muhammad committed
344
345
346
347
   ProcessList* pl = NULL;
   UsersTable* ut = UsersTable_new();

   pl = ProcessList_new(ut);
348
   Process_getMaxPid();
Hisham Muhammad's avatar
Hisham Muhammad committed
349
350
   
   Header* header = Header_new(pl);
351
   settings = Settings_new(pl, header, pl->cpuCount);
Hisham Muhammad's avatar
Hisham Muhammad committed
352
353
354
355
356
   int headerHeight = Header_calculateHeight(header);

   // FIXME: move delay code to settings
   if (delay != -1)
      settings->delay = delay;
357
358
   if (!usecolors) 
      settings->colorScheme = COLORSCHEME_MONOCHROME;
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386

   if (treeType == TREE_TYPE_AUTO) {
#ifdef HAVE_LIBNCURSESW
      char *locale = setlocale(LC_ALL, NULL);
      if (locale == NULL || locale[0] == '\0')
         locale = setlocale(LC_CTYPE, NULL);
      if (locale != NULL &&
          (strstr(locale, "UTF-8") ||
           strstr(locale, "utf-8") ||
           strstr(locale, "UTF8")  ||
           strstr(locale, "utf8")))
         treeType = TREE_TYPE_UTF8;
      else
         treeType = TREE_TYPE_ASCII;
#else
      treeType = TREE_TYPE_ASCII;
#endif
   }
   switch (treeType) {
   default:
   case TREE_TYPE_ASCII:
      pl->treeStr = ProcessList_treeStrAscii;
      break;
   case TREE_TYPE_UTF8:
      pl->treeStr = ProcessList_treeStrUtf8;
      break;
   }

Hisham Muhammad's avatar
Hisham Muhammad committed
387
388
389
   
   CRT_init(settings->delay, settings->colorScheme);
   
390
   panel = Panel_new(0, headerHeight, COLS, LINES - headerHeight - 2, PROCESS_CLASS, false, NULL);
391
392
393
394
395
   if (sortKey > 0) {
      pl->sortKey = sortKey;
      pl->treeView = false;
      pl->direction = 1;
   }
396
   ProcessList_printHeader(pl, Panel_getHeader(panel));
Hisham Muhammad's avatar
Hisham Muhammad committed
397
398
399
400
401
402

   IncBuffer incSearch, incFilter;
   bool filtering = false;

   memset(&incSearch, 0, sizeof(IncBuffer));
   const char* searchFunctions[] = {"Next  ", "Cancel ", " Search: ", NULL};
Hisham Muhammad's avatar
Hisham Muhammad committed
403
   const char* searchKeys[] = {"F3", "Esc", "  "};
Hisham Muhammad's avatar
Hisham Muhammad committed
404
   int searchEvents[] = {KEY_F(3), 27, ERR};
Hisham Muhammad's avatar
Hisham Muhammad committed
405
406
407
408
409
410
411
   incSearch.bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents);

   memset(&incFilter, 0, sizeof(IncBuffer));
   const char* filterFunctions[] = {"Done  ", "Clear ", " Filter: ", NULL};
   const char* filterKeys[] = {"Enter", "Esc", "  "};
   int filterEvents[] = {13, 27, ERR};
   incFilter.bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents);
Hisham Muhammad's avatar
Hisham Muhammad committed
412
   
Hisham Muhammad's avatar
Hisham Muhammad committed
413
414
415
   IncBuffer* incMode = NULL;
   
   const char* defaultFunctions[] = {"Help  ", "Setup ", "Search", "Filter", "Tree  ",
Hisham Muhammad's avatar
Hisham Muhammad committed
416
417
       "SortBy", "Nice -", "Nice +", "Kill  ", "Quit  ", NULL};
   FunctionBar* defaultBar = FunctionBar_new(defaultFunctions, NULL, NULL);
Hisham Muhammad's avatar
Hisham Muhammad committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431

   ProcessList_scan(pl);
   usleep(75000);
   
   FunctionBar_draw(defaultBar, NULL);
   
   int acc = 0;
   bool follow = false;
 
   struct timeval tv;
   double newTime = 0.0;
   double oldTime = 0.0;
   bool recalculate;

432
   int ch = ERR;
Hisham Muhammad's avatar
Hisham Muhammad committed
433
434
435
436
437
438
439
440
441
   int closeTimeout = 0;

   while (!quit) {
      gettimeofday(&tv, NULL);
      newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
      recalculate = (newTime - oldTime > CRT_delay);
      if (recalculate)
         oldTime = newTime;
      if (doRefresh) {
Hisham Muhammad's avatar
Hisham Muhammad committed
442

Hisham Muhammad's avatar
Hisham Muhammad committed
443
         int currPos = Panel_getSelectedIndex(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
444
         pid_t currPid = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
445
         int currScrollV = panel->scrollV;
Hisham Muhammad's avatar
Hisham Muhammad committed
446
447
         if (follow)
            currPid = ProcessList_get(pl, currPos)->pid;
Hisham Muhammad's avatar
Hisham Muhammad committed
448
         if (recalculate || doRecalculate) {
Hisham Muhammad's avatar
Hisham Muhammad committed
449
            ProcessList_scan(pl);
Hisham Muhammad's avatar
Hisham Muhammad committed
450
451
            doRecalculate = false;
         }
452
         if (refreshTimeout == 0 || pl->treeView) {
Hisham Muhammad's avatar
Hisham Muhammad committed
453
454
455
            ProcessList_sort(pl);
            refreshTimeout = 1;
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
456
         Panel_prune(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
457
         int size = ProcessList_size(pl);
Hisham Muhammad's avatar
Hisham Muhammad committed
458
         int idx = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
459
         for (int i = 0; i < size; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
460
            bool hidden = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
461
            Process* p = ProcessList_get(pl, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
462
463
464
465
466
467
468

            if ( (!p->show)
               || (userOnly && (p->st_uid != userId))
               || (filtering && !(String_contains_i(p->comm, incFilter.buffer))) )
               hidden = true;

            if (!hidden) {
Hisham Muhammad's avatar
Hisham Muhammad committed
469
470
471
               Panel_set(panel, idx, (Object*)p);
               if ((!follow && idx == currPos) || (follow && p->pid == currPid)) {
                  Panel_setSelected(panel, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
472
                  panel->scrollV = currScrollV;
Hisham Muhammad's avatar
Hisham Muhammad committed
473
               }
Hisham Muhammad's avatar
Hisham Muhammad committed
474
               idx++;
Hisham Muhammad's avatar
Hisham Muhammad committed
475
476
477
478
479
480
481
            }
         }
      }
      doRefresh = true;
      
      Header_draw(header);

Hisham Muhammad's avatar
Hisham Muhammad committed
482
      Panel_draw(panel, true);
Hisham Muhammad's avatar
Hisham Muhammad committed
483
      int prev = ch;
484
485
      if (incMode)
         move(LINES-1, CRT_cursorX);
Hisham Muhammad's avatar
Hisham Muhammad committed
486
487
488
      ch = getch();

      if (ch == ERR) {
Hisham Muhammad's avatar
Hisham Muhammad committed
489
         if (!incMode)
Hisham Muhammad's avatar
Hisham Muhammad committed
490
491
492
            refreshTimeout--;
         if (prev == ch && !recalculate) {
            closeTimeout++;
493
            if (closeTimeout == 100) {
Hisham Muhammad's avatar
Hisham Muhammad committed
494
               break;
495
            }
Hisham Muhammad's avatar
Hisham Muhammad committed
496
497
498
499
500
         } else
            closeTimeout = 0;
         continue;
      }

Hisham Muhammad's avatar
Hisham Muhammad committed
501
      if (incMode) {
Hisham Muhammad's avatar
Hisham Muhammad committed
502
         doRefresh = false;
503
         int size = Panel_size(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
504
         if (ch == KEY_F(3)) {
Hisham Muhammad's avatar
Hisham Muhammad committed
505
            int here = Panel_getSelectedIndex(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
506
507
508
509
            int i = here+1;
            while (i != here) {
               if (i == size)
                  i = 0;
510
               Process* p = (Process*) Panel_get(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
511
               if (String_contains_i(p->comm, incMode->buffer)) {
Hisham Muhammad's avatar
Hisham Muhammad committed
512
                  Panel_setSelected(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
513
514
515
516
517
                  break;
               }
               i++;
            }
            continue;
Hisham Muhammad's avatar
Hisham Muhammad committed
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
         } else if (isprint((char)ch) && (incMode->index < INCSEARCH_MAX)) {
            incMode->buffer[incMode->index] = ch;
            incMode->index++;
            incMode->buffer[incMode->index] = 0;
            if (incMode == &incFilter) {
               doRefresh = true;
               if (incFilter.index == 1) filtering = true;
            }
         } else if ((ch == KEY_BACKSPACE || ch == 127) && (incMode->index > 0)) {
            incMode->index--;
            incMode->buffer[incMode->index] = 0;
            if (incMode == &incFilter) {
               doRefresh = true;
               if (incFilter.index == 0) {
                  filtering = false;
                  IncBuffer_reset(incMode);
               }
            }
Hisham Muhammad's avatar
Hisham Muhammad committed
536
         } else {
Hisham Muhammad's avatar
Hisham Muhammad committed
537
538
539
540
541
542
543
544
            if (incMode == &incFilter) {
               doRefresh = true;
               if (ch == 27) {
                  filtering = false;
                  IncBuffer_reset(incMode);
               }
            }
            incMode = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
545
546
547
548
549
            FunctionBar_draw(defaultBar, NULL);
            continue;
         }

         bool found = false;
550
551
         for (int i = 0; i < size; i++) {
            Process* p = (Process*) Panel_get(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
552
            if (String_contains_i(p->comm, incSearch.buffer)) {
Hisham Muhammad's avatar
Hisham Muhammad committed
553
               Panel_setSelected(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
554
555
556
557
558
               found = true;
               break;
            }
         }
         if (found)
Hisham Muhammad's avatar
Hisham Muhammad committed
559
            FunctionBar_draw(incMode->bar, incMode->buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
560
         else
Hisham Muhammad's avatar
Hisham Muhammad committed
561
            FunctionBar_drawAttr(incMode->bar, incMode->buffer, CRT_colors[FAILED_SEARCH]);
Hisham Muhammad's avatar
Hisham Muhammad committed
562
563
564
         continue;
      }
      if (isdigit((char)ch)) {
Hisham Muhammad's avatar
Hisham Muhammad committed
565
         pid_t pid = ch-48 + acc;
Hisham Muhammad's avatar
Hisham Muhammad committed
566
567
         for (int i = 0; i < ProcessList_size(pl) && ((Process*) Panel_getSelected(panel))->pid != pid; i++)
            Panel_setSelected(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
568
569
570
571
572
573
574
575
576
577
578
579
         acc = pid * 10;
         if (acc > 100000)
            acc = 0;
         continue;
      } else {
         acc = 0;
      }

      if (ch == KEY_MOUSE) {
         MEVENT mevent;
         int ok = getmouse(&mevent);
         if (ok == OK) {
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
            if (mevent.bstate & BUTTON1_CLICKED) {
               if (mevent.y == panel->y) {
                  int x = panel->scrollH + mevent.x + 1;
                  ProcessField field = ProcessList_keyAt(pl, x);
                  if (field == pl->sortKey) {
                     ProcessList_invertSortOrder(pl);
                     pl->treeView = false;
                  } else {
                     setSortKey(pl, field, panel, settings);
                  }
                  refreshTimeout = 0;
                  continue;
               } 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;
               } if (mevent.y == LINES - 1) {
                  FunctionBar* bar;
Hisham Muhammad's avatar
Hisham Muhammad committed
600
                  if (incMode) bar = incMode->bar;
601
602
                  else bar = defaultBar;
                  ch = FunctionBar_synthesizeEvent(bar, mevent.x);
603
               }
604
605
606
607
608
609
            } else if (mevent.bstate & BUTTON4_CLICKED) {
               ch = KEY_UP;
            #if NCURSES_MOUSE_VERSION > 1
            } else if (mevent.bstate & BUTTON5_CLICKED) {
               ch = KEY_DOWN;
            #endif
Hisham Muhammad's avatar
Hisham Muhammad committed
610
611
612
613
614
615
            }
         }
      }

      switch (ch) {
      case KEY_RESIZE:
Hisham Muhammad's avatar
Hisham Muhammad committed
616
         Panel_resize(panel, COLS, LINES-headerHeight-1);
Hisham Muhammad's avatar
Hisham Muhammad committed
617
618
         if (incMode)
            FunctionBar_draw(incMode->bar, incMode->buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
619
620
621
622
623
624
         else
            FunctionBar_draw(defaultBar, NULL);
         break;
      case 'M':
      {
         refreshTimeout = 0;
625
         setSortKey(pl, PERCENT_MEM, panel, settings);
Hisham Muhammad's avatar
Hisham Muhammad committed
626
627
628
629
630
         break;
      }
      case 'T':
      {
         refreshTimeout = 0;
631
         setSortKey(pl, TIME, panel, settings);
Hisham Muhammad's avatar
Hisham Muhammad committed
632
633
634
635
         break;
      }
      case 'U':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
636
         for (int i = 0; i < Panel_size(panel); i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
637
            Process* p = (Process*) Panel_get(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
638
639
640
641
642
643
644
645
            p->tag = false;
         }
         doRefresh = true;
         break;
      }
      case 'P':
      {
         refreshTimeout = 0;
646
         setSortKey(pl, PERCENT_CPU, panel, settings);
Hisham Muhammad's avatar
Hisham Muhammad committed
647
648
649
650
         break;
      }
      case KEY_F(1):
      case 'h':
651
      case '?':
Hisham Muhammad's avatar
Hisham Muhammad committed
652
      {
653
         showHelp(pl);
Hisham Muhammad's avatar
Hisham Muhammad committed
654
655
656
657
658
659
660
661
662
663
664
665
666
         FunctionBar_draw(defaultBar, NULL);
         refreshTimeout = 0;
         break;
      }
      case '\014': // Ctrl+L
      {
         clear();
         FunctionBar_draw(defaultBar, NULL);
         refreshTimeout = 0;
         break;
      }
      case ' ':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
667
         Process* p = (Process*) Panel_getSelected(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
668
         Process_toggleTag(p);
Hisham Muhammad's avatar
Hisham Muhammad committed
669
         Panel_onKey(panel, KEY_DOWN);
Hisham Muhammad's avatar
Hisham Muhammad committed
670
671
672
673
         break;
      }
      case 's':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
674
         TraceScreen* ts = TraceScreen_new((Process*) Panel_getSelected(panel));
Hisham Muhammad's avatar
Hisham Muhammad committed
675
676
677
678
679
680
681
682
         TraceScreen_run(ts);
         TraceScreen_delete(ts);
         clear();
         FunctionBar_draw(defaultBar, NULL);
         refreshTimeout = 0;
         CRT_enableDelay();
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
683
684
685
686
687
688
689
690
691
692
693
      case 'l':
      {
         OpenFilesScreen* ts = OpenFilesScreen_new((Process*) Panel_getSelected(panel));
         OpenFilesScreen_run(ts);
         OpenFilesScreen_delete(ts);
         clear();
         FunctionBar_draw(defaultBar, NULL);
         refreshTimeout = 0;
         CRT_enableDelay();
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
694
695
696
697
      case 'S':
      case 'C':
      case KEY_F(2):
      {
698
         Setup_run(settings, header);
Hisham Muhammad's avatar
Hisham Muhammad committed
699
         // TODO: shouldn't need this, colors should be dynamic
700
         ProcessList_printHeader(pl, Panel_getHeader(panel));
Hisham Muhammad's avatar
Hisham Muhammad committed
701
         headerHeight = Header_calculateHeight(header);
Hisham Muhammad's avatar
Hisham Muhammad committed
702
703
         Panel_move(panel, 0, headerHeight);
         Panel_resize(panel, COLS, LINES-headerHeight-1);
Hisham Muhammad's avatar
Hisham Muhammad committed
704
705
706
707
708
709
710
711
712
713
714
         FunctionBar_draw(defaultBar, NULL);
         refreshTimeout = 0;
         break;
      }
      case 'F':
      {
         follow = true;
         continue;
      }
      case 'u':
      {
715
         Panel* usersPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true, ListItem_compare);
Hisham Muhammad's avatar
Hisham Muhammad committed
716
         Panel_setHeader(usersPanel, "Show processes of:");
Hisham Muhammad's avatar
Hisham Muhammad committed
717
         UsersTable_foreach(ut, addUserToVector, usersPanel);
718
         Vector_insertionSort(usersPanel->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
719
         ListItem* allUsers = ListItem_new("All users", -1);
Hisham Muhammad's avatar
Hisham Muhammad committed
720
         Panel_insert(usersPanel, 0, (Object*) allUsers);
Hisham Muhammad's avatar
Hisham Muhammad committed
721
         const char* fuFunctions[] = {"Show    ", "Cancel ", NULL};
722
         ListItem* picked = (ListItem*) pickFromVector(panel, usersPanel, 20, headerHeight, fuFunctions, defaultBar, header);
Hisham Muhammad's avatar
Hisham Muhammad committed
723
724
725
726
727
728
729
         if (picked) {
            if (picked == allUsers) {
               userOnly = false;
            } else {
               setUserOnly(ListItem_getRef(picked), &userOnly, &userId);
            }
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
730
         Panel_delete((Object*)usersPanel);
Hisham Muhammad's avatar
Hisham Muhammad committed
731
732
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
733
734
735
736
737
738
739
740
741
742
      case '+':
      case '=':
      case '-':
      {
         Process* p = (Process*) Panel_getSelected(panel);
         p->showChildren = !p->showChildren;
         refreshTimeout = 0;
         doRecalculate = true;
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
743
744
745
      case KEY_F(9):
      case 'k':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
746
747
         if (!killPanel) {
            killPanel = (Panel*) SignalsPanel_new(0, 0, 0, 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
748
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
749
         SignalsPanel_reset((SignalsPanel*) killPanel);
Hisham Muhammad's avatar
Hisham Muhammad committed
750
         const char* fuFunctions[] = {"Send  ", "Cancel ", NULL};
Hisham Muhammad's avatar
Hisham Muhammad committed
751
         ListItem* sgn = (ListItem*) pickFromVector(panel, killPanel, 15, headerHeight, fuFunctions, defaultBar, header);
Hisham Muhammad's avatar
Hisham Muhammad committed
752
         if (sgn) {
Hisham Muhammad's avatar
Hisham Muhammad committed
753
            if (sgn->key != 0) {
Hisham Muhammad's avatar
Hisham Muhammad committed
754
755
               Panel_setHeader(panel, "Sending...");
               Panel_draw(panel, true);
Hisham Muhammad's avatar
Hisham Muhammad committed
756
757
               refresh();
               bool anyTagged = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
758
               for (int i = 0; i < Panel_size(panel); i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
759
                  Process* p = (Process*) Panel_get(panel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
760
                  if (p->tag) {
Hisham Muhammad's avatar
Hisham Muhammad committed
761
                     Process_sendSignal(p, sgn->key);
Hisham Muhammad's avatar
Hisham Muhammad committed
762
763
764
765
                     anyTagged = true;
                  }
               }
               if (!anyTagged) {
Hisham Muhammad's avatar
Hisham Muhammad committed
766
                  Process* p = (Process*) Panel_getSelected(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
767
                  Process_sendSignal(p, sgn->key);
Hisham Muhammad's avatar
Hisham Muhammad committed
768
769
770
771
               }
               napms(500);
            }
         }
772
         ProcessList_printHeader(pl, Panel_getHeader(panel));
Hisham Muhammad's avatar
Hisham Muhammad committed
773
774
775
         refreshTimeout = 0;
         break;
      }
776
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
777
778
      case 'a':
      {
779
         if (pl->cpuCount == 1)
780
781
            break;

782
783
784
         Affinity* affinity = Process_getAffinity((Process*) Panel_getSelected(panel));
         Panel* affinityPanel = AffinityPanel_new(pl, affinity);
         Affinity_delete(affinity);
785

Hisham Muhammad's avatar
Hisham Muhammad committed
786
         const char* fuFunctions[] = {"Set    ", "Cancel ", NULL};
787
         void* set = pickFromVector(panel, affinityPanel, 15, headerHeight, fuFunctions, defaultBar, header);
788
         if (set) {
789
            Affinity* affinity = AffinityPanel_getAffinity(affinityPanel);
790
791
            bool anyTagged = false;
            bool ok = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
792
            for (int i = 0; i < Panel_size(panel); i++) {
793
794
               Process* p = (Process*) Panel_get(panel, i);
               if (p->tag) {
795
                  ok = Process_setAffinity(p, affinity) && ok;
796
797
                  anyTagged = true;
               }
798
            }
799
800
            if (!anyTagged) {
               Process* p = (Process*) Panel_getSelected(panel);
801
               ok = Process_setAffinity(p, affinity) && ok;
802
803
804
            }
            if (!ok)
               beep();
805
            Affinity_delete(affinity);
806
         }
807
         Panel_delete((Object*)affinityPanel);
808
         ProcessList_printHeader(pl, Panel_getHeader(panel));
809
810
811
         refreshTimeout = 0;
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
812
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
813
814
815
816
817
818
819
820
821
822
823
      case KEY_F(10):
      case 'q':
         quit = 1;
         break;
      case '<':
      case ',':
      case KEY_F(18):
      case '>':
      case '.':
      case KEY_F(6):
      {
824
         Panel* sortPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true, ListItem_compare);
Hisham Muhammad's avatar
Hisham Muhammad committed
825
         Panel_setHeader(sortPanel, "Sort by");
Hisham Muhammad's avatar
Hisham Muhammad committed
826
         const char* fuFunctions[] = {"Sort  ", "Cancel ", NULL};
Hisham Muhammad's avatar
Hisham Muhammad committed
827
828
         ProcessField* fields = pl->fields;
         for (int i = 0; fields[i]; i++) {
829
            char* name = String_trim(Process_fieldTitles[fields[i]]);
Hisham Muhammad's avatar
Hisham Muhammad committed
830
            Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
Hisham Muhammad's avatar
Hisham Muhammad committed
831
            if (fields[i] == pl->sortKey)
Hisham Muhammad's avatar
Hisham Muhammad committed
832
               Panel_setSelected(sortPanel, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
833
834
            free(name);
         }
835
         ListItem* field = (ListItem*) pickFromVector(panel, sortPanel, 15, headerHeight, fuFunctions, defaultBar, header);
Hisham Muhammad's avatar
Hisham Muhammad committed
836
837
         if (field) {
            settings->changed = true;
838
839
            setSortKey(pl, field->key, panel, settings);
         } else {
840
            ProcessList_printHeader(pl, Panel_getHeader(panel));
Hisham Muhammad's avatar
Hisham Muhammad committed
841
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
842
         ((Object*)sortPanel)->delete((Object*)sortPanel);
Hisham Muhammad's avatar
Hisham Muhammad committed
843
844
845
846
847
848
849
850
851
852
853
854
855
         refreshTimeout = 0;
         break;
      }
      case 'I':
      {
         refreshTimeout = 0;
         settings->changed = true;
         ProcessList_invertSortOrder(pl);
         break;
      }
      case KEY_F(8):
      case '[':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
856
         doRefresh = changePriority(panel, 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
857
858
859
860
861
         break;
      }
      case KEY_F(7):
      case ']':
      {
Hisham Muhammad's avatar
Hisham Muhammad committed
862
         doRefresh = changePriority(panel, -1);
Hisham Muhammad's avatar
Hisham Muhammad committed
863
864
865
866
         break;
      }
      case KEY_F(3):
      case '/':
Hisham Muhammad's avatar
Hisham Muhammad committed
867
868
869
         incMode = &incSearch;
         IncBuffer_reset(incMode);
         FunctionBar_draw(incSearch.bar, incSearch.buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
870
         break;
Hisham Muhammad's avatar
Hisham Muhammad committed
871
872
873
874
875
876
877
      case KEY_F(4):
      case '\\':
         incMode = &incFilter;
         refreshTimeout = 0;
         doRefresh = true;
         FunctionBar_draw(incFilter.bar, incFilter.buffer);
         continue;
Hisham Muhammad's avatar
Hisham Muhammad committed
878
879
880
881
      case 't':
      case KEY_F(5):
         refreshTimeout = 0;
         pl->treeView = !pl->treeView;
882
         ProcessList_expandTree(pl);
Hisham Muhammad's avatar
Hisham Muhammad committed
883
884
885
         settings->changed = true;
         break;
      case 'H':
Hisham Muhammad's avatar
Hisham Muhammad committed
886
         doRecalculate = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
887
         refreshTimeout = 0;
888
889
         pl->hideUserlandThreads = !pl->hideUserlandThreads;
         pl->hideThreads = pl->hideUserlandThreads;
Hisham Muhammad's avatar
Hisham Muhammad committed
890
891
892
         settings->changed = true;
         break;
      case 'K':
Hisham Muhammad's avatar
Hisham Muhammad committed
893
         doRecalculate = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
894
895
896
897
898
899
900
         refreshTimeout = 0;
         pl->hideKernelThreads = !pl->hideKernelThreads;
         settings->changed = true;
         break;
      default:
         doRefresh = false;
         refreshTimeout = resetRefreshTimeout;
Hisham Muhammad's avatar
Hisham Muhammad committed
901
         Panel_onKey(panel, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
902
903
904
905
906
907
908
909
910
911
912
913
914
915
         break;
      }
      follow = false;
   }
   attron(CRT_colors[RESET_COLOR]);
   mvhline(LINES-1, 0, ' ', COLS);
   attroff(CRT_colors[RESET_COLOR]);
   refresh();
   
   CRT_done();
   if (settings->changed)
      Settings_write(settings);
   Header_delete(header);
   ProcessList_delete(pl);
Hisham Muhammad's avatar
Hisham Muhammad committed
916
917
   FunctionBar_delete((Object*)incFilter.bar);
   FunctionBar_delete((Object*)incSearch.bar);
Hisham Muhammad's avatar
Hisham Muhammad committed
918
   FunctionBar_delete((Object*)defaultBar);
Hisham Muhammad's avatar
Hisham Muhammad committed
919
   Panel_delete((Object*)panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
920
921
   if (killPanel)
      ((Object*)killPanel)->delete((Object*)killPanel);
Hisham Muhammad's avatar
Hisham Muhammad committed
922
923
924
925
926
   UsersTable_delete(ut);
   Settings_delete(settings);
   debug_done();
   return 0;
}