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

#include "Settings.h"
9
#include "Platform.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
10

David Hunt's avatar
David Hunt committed
11
#include "StringUtils.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
12
#include "Vector.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
13
#include "CRT.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
14

Hisham Muhammad's avatar
Hisham Muhammad committed
15
16
17
18
19
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

Hisham Muhammad's avatar
Hisham Muhammad committed
20
21
22
#define DEFAULT_DELAY 15

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
23
#include "Process.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
24
#include <stdbool.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
25

Hisham Muhammad's avatar
Hisham Muhammad committed
26
27
28
29
30
typedef struct {
   int len;
   char** names;
   int* modes;
} MeterColumnSettings;
31

Hisham Muhammad's avatar
Hisham Muhammad committed
32
typedef struct Settings_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
33
34
35
36
37
38
   char* filename;
   
   MeterColumnSettings columns[2];

   ProcessField* fields;
   int flags;
Hisham Muhammad's avatar
Hisham Muhammad committed
39
40
   int colorScheme;
   int delay;
Hisham Muhammad's avatar
Hisham Muhammad committed
41

42
   int cpuCount;
Hisham Muhammad's avatar
Hisham Muhammad committed
43
44
45
46
47
48
   int direction;
   ProcessField sortKey;

   bool countCPUsFromZero;
   bool detailedCPUTime;
   bool treeView;
49
   bool showProgramPath;
Hisham Muhammad's avatar
Hisham Muhammad committed
50
51
52
53
54
55
56
57
58
59
60
61
   bool hideThreads;
   bool shadowOtherUsers;
   bool showThreadNames;
   bool hideKernelThreads;
   bool hideUserlandThreads;
   bool highlightBaseName;
   bool highlightMegabytes;
   bool highlightThreads;
   bool updateProcessNames;
   bool accountGuestInCPUMeter;
   bool headerMargin;

Hisham Muhammad's avatar
Hisham Muhammad committed
62
   bool changed;
Hisham Muhammad's avatar
Hisham Muhammad committed
63
64
} Settings;

Hisham Muhammad's avatar
Hisham Muhammad committed
65
66
67
68
#ifndef Settings_cpuId
#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1)
#endif

Hisham Muhammad's avatar
Hisham Muhammad committed
69
70
71
}*/

void Settings_delete(Settings* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
72
73
74
75
76
77
   free(this->filename);
   free(this->fields);
   for (unsigned int i = 0; i < (sizeof(this->columns)/sizeof(MeterColumnSettings)); i++) {
      String_freeArray(this->columns[i].names);
      free(this->columns[i].modes);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
78
79
80
   free(this);
}

Hisham Muhammad's avatar
Hisham Muhammad committed
81
static void Settings_readMeters(Settings* this, char* line, int column) {
Hisham Muhammad's avatar
Hisham Muhammad committed
82
   char* trim = String_trim(line);
83
84
   int nIds;
   char** ids = String_split(trim, ' ', &nIds);
Hisham Muhammad's avatar
Hisham Muhammad committed
85
   free(trim);
Hisham Muhammad's avatar
Hisham Muhammad committed
86
   this->columns[column].names = ids;
Hisham Muhammad's avatar
Hisham Muhammad committed
87
88
}

Hisham Muhammad's avatar
Hisham Muhammad committed
89
static void Settings_readMeterModes(Settings* this, char* line, int column) {
Hisham Muhammad's avatar
Hisham Muhammad committed
90
   char* trim = String_trim(line);
91
92
   int nIds;
   char** ids = String_split(trim, ' ', &nIds);
Hisham Muhammad's avatar
Hisham Muhammad committed
93
   free(trim);
Hisham Muhammad's avatar
Hisham Muhammad committed
94
   int len = 0;
95
   for (int i = 0; ids[i]; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
96
97
98
      len++;
   }
   this->columns[column].len = len;
Hisham's avatar
Hisham committed
99
   int* modes = xCalloc(len, sizeof(int));
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
   for (int i = 0; i < len; i++) {
      modes[i] = atoi(ids[i]);
Hisham Muhammad's avatar
Hisham Muhammad committed
102
103
   }
   String_freeArray(ids);
Hisham Muhammad's avatar
Hisham Muhammad committed
104
   this->columns[column].modes = modes;
Hisham Muhammad's avatar
Hisham Muhammad committed
105
106
}

107
static void Settings_defaultMeters(Settings* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
108
   int sizes[] = { 3, 3 };
109
   if (this->cpuCount > 4) {
Hisham Muhammad's avatar
Hisham Muhammad committed
110
111
112
      sizes[1]++;
   }
   for (int i = 0; i < 2; i++) {
Hisham's avatar
Hisham committed
113
114
      this->columns[i].names = xCalloc(sizes[i] + 1, sizeof(char*));
      this->columns[i].modes = xCalloc(sizes[i], sizeof(int));
115
      this->columns[i].len = sizes[i];
Hisham Muhammad's avatar
Hisham Muhammad committed
116
117
118
   }
   
   int r = 0;
119
   if (this->cpuCount > 8) {
Hisham's avatar
Hisham committed
120
      this->columns[0].names[0] = xStrdup("LeftCPUs2");
121
122
123
      this->columns[0].modes[0] = BAR_METERMODE;
      this->columns[1].names[r] = xStrdup("RightCPUs2");
      this->columns[1].modes[r++] = BAR_METERMODE;
124
   } else if (this->cpuCount > 4) {
Hisham's avatar
Hisham committed
125
      this->columns[0].names[0] = xStrdup("LeftCPUs");
126
127
128
      this->columns[0].modes[0] = BAR_METERMODE;
      this->columns[1].names[r] = xStrdup("RightCPUs");
      this->columns[1].modes[r++] = BAR_METERMODE;
129
   } else {
Hisham's avatar
Hisham committed
130
      this->columns[0].names[0] = xStrdup("AllCPUs");
131
      this->columns[0].modes[0] = BAR_METERMODE;
Hisham Muhammad's avatar
Hisham Muhammad committed
132
   }
Hisham's avatar
Hisham committed
133
   this->columns[0].names[1] = xStrdup("Memory");
134
   this->columns[0].modes[1] = BAR_METERMODE;
Hisham's avatar
Hisham committed
135
   this->columns[0].names[2] = xStrdup("Swap");
136
   this->columns[0].modes[2] = BAR_METERMODE;
Hisham Muhammad's avatar
Hisham Muhammad committed
137
   
138
139
140
141
142
143
   this->columns[1].names[r] = xStrdup("Tasks");
   this->columns[1].modes[r++] = TEXT_METERMODE;
   this->columns[1].names[r] = xStrdup("LoadAverage");
   this->columns[1].modes[r++] = TEXT_METERMODE;
   this->columns[1].names[r] = xStrdup("Uptime");
   this->columns[1].modes[r++] = TEXT_METERMODE;
Hisham Muhammad's avatar
Hisham Muhammad committed
144
145
146
147
148
149
150
151
152
}

static void readFields(ProcessField* fields, int* flags, const char* line) {
   char* trim = String_trim(line);
   int nIds;
   char** ids = String_split(trim, ' ', &nIds);
   free(trim);
   int i, j;
   *flags = 0;
153
   for (j = 0, i = 0; i < Platform_numberOfFields && ids[i]; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
      // This "+1" is for compatibility with the older enum format.
      int id = atoi(ids[i]) + 1;
156
      if (id > 0 && Process_fields[id].name && id < Platform_numberOfFields) {
Hisham Muhammad's avatar
Hisham Muhammad committed
157
158
159
160
         fields[j] = id;
         *flags |= Process_fields[id].flags;
         j++;
      }
161
   }
Hisham's avatar
Hisham committed
162
   fields[j] = NULL_PROCESSFIELD;
Hisham Muhammad's avatar
Hisham Muhammad committed
163
   String_freeArray(ids);
164
165
}

166
static bool Settings_read(Settings* this, const char* fileName) {
167
   FILE* fd;
168
169
   
   CRT_dropPrivileges();
170
   fd = fopen(fileName, "r");
171
   CRT_restorePrivileges();
172
   if (!fd)
Hisham Muhammad's avatar
Hisham Muhammad committed
173
      return false;
174
   
Hisham Muhammad's avatar
Hisham Muhammad committed
175
   bool readMeters = false;
176
177
178
179
180
   for (;;) {
      char* line = String_readLine(fd);
      if (!line) {
         break;
      }
181
      int nOptions;
182
183
      char** option = String_split(line, '=', &nOptions);
      free (line);
184
185
186
187
      if (nOptions < 2) {
         String_freeArray(option);
         continue;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
188
      if (String_eq(option[0], "fields")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
189
         readFields(this->fields, &(this->flags), option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
190
191
      } else if (String_eq(option[0], "sort_key")) {
         // This "+1" is for compatibility with the older enum format.
Hisham Muhammad's avatar
Hisham Muhammad committed
192
         this->sortKey = atoi(option[1]) + 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
193
      } else if (String_eq(option[0], "sort_direction")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
194
         this->direction = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
195
      } else if (String_eq(option[0], "tree_view")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
196
         this->treeView = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
197
      } else if (String_eq(option[0], "hide_threads")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
198
         this->hideThreads = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
199
      } else if (String_eq(option[0], "hide_kernel_threads")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
200
         this->hideKernelThreads = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
201
      } else if (String_eq(option[0], "hide_userland_threads")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
202
         this->hideUserlandThreads = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
203
      } else if (String_eq(option[0], "shadow_other_users")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
204
         this->shadowOtherUsers = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
205
      } else if (String_eq(option[0], "show_thread_names")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
206
         this->showThreadNames = atoi(option[1]);
207
208
      } else if (String_eq(option[0], "show_program_path")) {
         this->showProgramPath = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
209
      } else if (String_eq(option[0], "highlight_base_name")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
210
         this->highlightBaseName = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
211
      } else if (String_eq(option[0], "highlight_megabytes")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
212
         this->highlightMegabytes = atoi(option[1]);
213
      } else if (String_eq(option[0], "highlight_threads")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
214
         this->highlightThreads = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
215
      } else if (String_eq(option[0], "header_margin")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
216
         this->headerMargin = atoi(option[1]);
217
      } else if (String_eq(option[0], "expand_system_time")) {
218
         // Compatibility option.
Hisham Muhammad's avatar
Hisham Muhammad committed
219
         this->detailedCPUTime = atoi(option[1]);
220
      } else if (String_eq(option[0], "detailed_cpu_time")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
221
         this->detailedCPUTime = atoi(option[1]);
222
      } else if (String_eq(option[0], "cpu_count_from_zero")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
223
         this->countCPUsFromZero = atoi(option[1]);
224
      } else if (String_eq(option[0], "update_process_names")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
225
         this->updateProcessNames = atoi(option[1]);
226
      } else if (String_eq(option[0], "account_guest_in_cpu_meter")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
227
         this->accountGuestInCPUMeter = atoi(option[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
228
229
230
231
      } else if (String_eq(option[0], "delay")) {
         this->delay = atoi(option[1]);
      } else if (String_eq(option[0], "color_scheme")) {
         this->colorScheme = atoi(option[1]);
232
         if (this->colorScheme < 0 || this->colorScheme >= LAST_COLORSCHEME) this->colorScheme = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
233
      } else if (String_eq(option[0], "left_meters")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
234
         Settings_readMeters(this, option[1], 0);
235
         readMeters = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
236
      } else if (String_eq(option[0], "right_meters")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
237
         Settings_readMeters(this, option[1], 1);
238
         readMeters = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
239
      } else if (String_eq(option[0], "left_meter_modes")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
240
         Settings_readMeterModes(this, option[1], 0);
241
         readMeters = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
242
      } else if (String_eq(option[0], "right_meter_modes")) {
Hisham Muhammad's avatar
Hisham Muhammad committed
243
         Settings_readMeterModes(this, option[1], 1);
244
         readMeters = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
245
246
247
248
249
      }
      String_freeArray(option);
   }
   fclose(fd);
   if (!readMeters) {
250
      Settings_defaultMeters(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
251
252
253
254
   }
   return true;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
255
256
static void writeFields(FILE* fd, ProcessField* fields, const char* name) {
   fprintf(fd, "%s=", name);
257
   const char* sep = "";
Hisham Muhammad's avatar
Hisham Muhammad committed
258
259
   for (int i = 0; fields[i]; i++) {
      // This "-1" is for compatibility with the older enum format.
260
261
      fprintf(fd, "%s%d", sep, (int) fields[i]-1);
      sep = " ";
Hisham Muhammad's avatar
Hisham Muhammad committed
262
263
264
265
266
   }
   fprintf(fd, "\n");
}

static void writeMeters(Settings* this, FILE* fd, int column) {
267
   const char* sep = "";
Hisham Muhammad's avatar
Hisham Muhammad committed
268
   for (int i = 0; i < this->columns[column].len; i++) {
269
270
      fprintf(fd, "%s%s", sep, this->columns[column].names[i]);
      sep = " ";
Hisham Muhammad's avatar
Hisham Muhammad committed
271
272
273
274
275
   }
   fprintf(fd, "\n");
}

static void writeMeterModes(Settings* this, FILE* fd, int column) {
276
   const char* sep = "";
Hisham Muhammad's avatar
Hisham Muhammad committed
277
   for (int i = 0; i < this->columns[column].len; i++) {
278
279
      fprintf(fd, "%s%d", sep, this->columns[column].modes[i]);
      sep = " ";
Hisham Muhammad's avatar
Hisham Muhammad committed
280
281
282
283
   }
   fprintf(fd, "\n");
}

Hisham Muhammad's avatar
Hisham Muhammad committed
284
285
bool Settings_write(Settings* this) {
   FILE* fd;
286

287
   CRT_dropPrivileges();
Hisham Muhammad's avatar
Hisham Muhammad committed
288
   fd = fopen(this->filename, "w");
289
290
   CRT_restorePrivileges();

Hisham Muhammad's avatar
Hisham Muhammad committed
291
292
293
   if (fd == NULL) {
      return false;
   }
294
   fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n");
Hisham Muhammad's avatar
Hisham Muhammad committed
295
   fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n");
Hisham Muhammad's avatar
Hisham Muhammad committed
296
   writeFields(fd, this->fields, "fields");
Hisham Muhammad's avatar
Hisham Muhammad committed
297
   // This "-1" is for compatibility with the older enum format.
Hisham Muhammad's avatar
Hisham Muhammad committed
298
299
300
301
302
303
304
   fprintf(fd, "sort_key=%d\n", (int) this->sortKey-1);
   fprintf(fd, "sort_direction=%d\n", (int) this->direction);
   fprintf(fd, "hide_threads=%d\n", (int) this->hideThreads);
   fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads);
   fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads);
   fprintf(fd, "shadow_other_users=%d\n", (int) this->shadowOtherUsers);
   fprintf(fd, "show_thread_names=%d\n", (int) this->showThreadNames);
305
   fprintf(fd, "show_program_path=%d\n", (int) this->showProgramPath);
Hisham Muhammad's avatar
Hisham Muhammad committed
306
307
308
309
310
311
312
313
314
   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, "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);
   fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->countCPUsFromZero);
   fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames);
   fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter);
Hisham Muhammad's avatar
Hisham Muhammad committed
315
316
   fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
   fprintf(fd, "delay=%d\n", (int) this->delay);
Hisham Muhammad's avatar
Hisham Muhammad committed
317
318
319
320
   fprintf(fd, "left_meters="); writeMeters(this, fd, 0);
   fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
   fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
   fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
321
322
323
   fclose(fd);
   return true;
}
324

Hisham Muhammad's avatar
Hisham Muhammad committed
325
326
Settings* Settings_new(int cpuCount) {
  
Hisham's avatar
Hisham committed
327
   Settings* this = xCalloc(1, sizeof(Settings));
Hisham Muhammad's avatar
Hisham Muhammad committed
328
329
330
331
332
333
334
335
336
337
338
339
340
341

   this->sortKey = PERCENT_CPU;
   this->direction = 1;
   this->hideThreads = false;
   this->shadowOtherUsers = false;
   this->showThreadNames = false;
   this->hideKernelThreads = false;
   this->hideUserlandThreads = false;
   this->treeView = false;
   this->highlightBaseName = false;
   this->highlightMegabytes = false;
   this->detailedCPUTime = false;
   this->countCPUsFromZero = false;
   this->updateProcessNames = false;
342
   this->cpuCount = cpuCount;
343
   this->showProgramPath = true;
Hisham's avatar
Hisham committed
344
   this->highlightThreads = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
345
   
Hisham's avatar
Hisham committed
346
   this->fields = xCalloc(Platform_numberOfFields+1, sizeof(ProcessField));
Hisham Muhammad's avatar
Hisham Muhammad committed
347
348
349
   // TODO: turn 'fields' into a Vector,
   // (and ProcessFields into proper objects).
   this->flags = 0;
350
   ProcessField* defaults = Platform_defaultFields;
Hisham Muhammad's avatar
Hisham Muhammad committed
351
352
353
354
355
   for (int i = 0; defaults[i]; i++) {
      this->fields[i] = defaults[i];
      this->flags |= Process_fields[defaults[i]].flags;
   }

356
357
358
   char* legacyDotfile = NULL;
   char* rcfile = getenv("HTOPRC");
   if (rcfile) {
Hisham's avatar
Hisham committed
359
      this->filename = xStrdup(rcfile);
360
361
362
363
364
365
366
   } else {
      const char* home = getenv("HOME");
      if (!home) home = "";
      const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
      char* configDir = NULL;
      char* htopDir = NULL;
      if (xdgConfigHome) {
Hisham Muhammad's avatar
Hisham Muhammad committed
367
         this->filename = String_cat(xdgConfigHome, "/htop/htoprc");
Hisham's avatar
Hisham committed
368
         configDir = xStrdup(xdgConfigHome);
369
370
         htopDir = String_cat(xdgConfigHome, "/htop");
      } else {
Hisham Muhammad's avatar
Hisham Muhammad committed
371
         this->filename = String_cat(home, "/.config/htop/htoprc");
372
373
374
375
         configDir = String_cat(home, "/.config");
         htopDir = String_cat(home, "/.config/htop");
      }
      legacyDotfile = String_cat(home, "/.htoprc");
376
377
      
      CRT_dropPrivileges();
378
379
      (void) mkdir(configDir, 0700);
      (void) mkdir(htopDir, 0700);
380
381
      free(htopDir);
      free(configDir);
382
      struct stat st;
383
384
385
      if (lstat(legacyDotfile, &st) != 0) {
         st.st_mode = 0;
      }
386
      if (access(legacyDotfile, R_OK) != 0 || S_ISLNK(st.st_mode)) {
387
388
389
         free(legacyDotfile);
         legacyDotfile = NULL;
      }
390
      CRT_restorePrivileges();
391
   }
392
393
394
   this->colorScheme = 0;
   this->changed = false;
   this->delay = DEFAULT_DELAY;
395
   bool ok = Settings_read(this, legacyDotfile ? legacyDotfile : this->filename);
396
397
398
399
400
401
402
   if (ok) {
      if (legacyDotfile) {
         // Transition to new location and delete old configuration file
         if (Settings_write(this))
            unlink(legacyDotfile);
      }
   } else {
403
404
405
      this->changed = true;
      // TODO: how to get SYSCONFDIR correctly through Autoconf?
      char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
406
      ok = Settings_read(this, systemSettings);
407
408
      free(systemSettings);
      if (!ok) {
409
         Settings_defaultMeters(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
410
411
         this->hideKernelThreads = true;
         this->highlightMegabytes = true;
Hisham's avatar
Hisham committed
412
         this->highlightThreads = true;
413
         this->headerMargin = true;
414
415
      }
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
416
   free(legacyDotfile);
417
418
   return this;
}
Hisham Muhammad's avatar
Hisham Muhammad committed
419
420
421
422
423
424
425

void Settings_invertSortOrder(Settings* this) {
   if (this->direction == 1)
      this->direction = -1;
   else
      this->direction = 1;
}