aboutsummaryrefslogtreecommitdiffstats
path: root/Settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'Settings.c')
-rw-r--r--Settings.c137
1 files changed, 109 insertions, 28 deletions
diff --git a/Settings.c b/Settings.c
index 8543b9e..a01e249 100644
--- a/Settings.c
+++ b/Settings.c
@@ -5,6 +5,8 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/
+#include "config.h" // IWYU pragma: keep
+
#include "Settings.h"
#include <ctype.h>
@@ -19,9 +21,12 @@ in the source distribution for its full text.
#include "CRT.h"
#include "DynamicColumn.h"
+#include "DynamicScreen.h"
#include "Macros.h"
#include "Meter.h"
#include "Platform.h"
+#include "Process.h"
+#include "Table.h"
#include "XUtils.h"
@@ -203,13 +208,25 @@ static void Settings_defaultMeters(Settings* this, unsigned int initialCpuCount)
this->hColumns[1].modes[r++] = TEXT_METERMODE;
}
-static const char* toFieldName(Hashtable* columns, int id) {
- if (id < 0)
+static const char* toFieldName(Hashtable* columns, int id, bool* enabled) {
+ if (id < 0) {
+ if (enabled)
+ *enabled = false;
return NULL;
- if (id >= LAST_PROCESSFIELD) {
+ }
+ if (id >= ROW_DYNAMIC_FIELDS) {
const DynamicColumn* column = DynamicColumn_lookup(columns, id);
+ if (!column) {
+ if (enabled)
+ *enabled = false;
+ return NULL;
+ }
+ if (enabled)
+ *enabled = column->enabled;
return column->name;
}
+ if (enabled)
+ *enabled = true;
return Process_fields[id].name;
}
@@ -217,7 +234,7 @@ static int toFieldIndex(Hashtable* columns, const char* str) {
if (isdigit(str[0])) {
// This "+1" is for compatibility with the older enum format.
int id = atoi(str) + 1;
- if (toFieldName(columns, id)) {
+ if (toFieldName(columns, id, NULL)) {
return id;
}
} else {
@@ -237,7 +254,7 @@ static int toFieldIndex(Hashtable* columns, const char* str) {
}
// Fallback to iterative scan of table of fields by-name.
for (int p = 1; p < LAST_PROCESSFIELD; p++) {
- const char* pName = toFieldName(columns, p);
+ const char* pName = toFieldName(columns, p, NULL);
if (pName && strcmp(pName, str) == 0)
return p;
}
@@ -269,34 +286,57 @@ static void ScreenSettings_readFields(ScreenSettings* ss, Hashtable* columns, co
String_freeArray(ids);
}
+static ScreenSettings* Settings_initScreenSettings(ScreenSettings* ss, Settings* this, const char* columns) {
+ ScreenSettings_readFields(ss, this->dynamicColumns, columns);
+ this->screens[this->nScreens] = ss;
+ this->nScreens++;
+ this->screens = xRealloc(this->screens, sizeof(ScreenSettings*) * (this->nScreens + 1));
+ this->screens[this->nScreens] = NULL;
+ return ss;
+}
+
ScreenSettings* Settings_newScreen(Settings* this, const ScreenDefaults* defaults) {
int sortKey = defaults->sortKey ? toFieldIndex(this->dynamicColumns, defaults->sortKey) : PID;
+ int treeSortKey = defaults->treeSortKey ? toFieldIndex(this->dynamicColumns, defaults->treeSortKey) : PID;
int sortDesc = (sortKey >= 0 && sortKey < LAST_PROCESSFIELD) ? Process_fields[sortKey].defaultSortDesc : 1;
ScreenSettings* ss = xMalloc(sizeof(ScreenSettings));
*ss = (ScreenSettings) {
- .name = xStrdup(defaults->name),
+ .heading = xStrdup(defaults->name),
+ .dynamic = NULL,
+ .table = NULL,
.fields = xCalloc(LAST_PROCESSFIELD, sizeof(ProcessField)),
.flags = 0,
.direction = sortDesc ? -1 : 1,
.treeDirection = 1,
.sortKey = sortKey,
- .treeSortKey = PID,
+ .treeSortKey = treeSortKey,
.treeView = false,
.treeViewAlwaysByPID = false,
.allBranchesCollapsed = false,
};
+ return Settings_initScreenSettings(ss, this, defaults->columns);
+}
- ScreenSettings_readFields(ss, this->dynamicColumns, defaults->columns);
- this->screens[this->nScreens] = ss;
- this->nScreens++;
- this->screens = xRealloc(this->screens, sizeof(ScreenSettings*) * (this->nScreens + 1));
- this->screens[this->nScreens] = NULL;
- return ss;
+ScreenSettings* Settings_newDynamicScreen(Settings* this, const char* tab, const DynamicScreen* screen, Table* table) {
+ int sortKey = toFieldIndex(this->dynamicColumns, screen->columnKeys);
+
+ ScreenSettings* ss = xMalloc(sizeof(ScreenSettings));
+ *ss = (ScreenSettings) {
+ .heading = xStrdup(tab),
+ .dynamic = xStrdup(screen->name),
+ .table = table,
+ .fields = xCalloc(LAST_PROCESSFIELD, sizeof(ProcessField)),
+ .direction = screen->direction,
+ .treeDirection = 1,
+ .sortKey = sortKey,
+ };
+ return Settings_initScreenSettings(ss, this, screen->columnKeys);
}
void ScreenSettings_delete(ScreenSettings* this) {
- free(this->name);
+ free(this->heading);
+ free(this->dynamic);
free(this->fields);
free(this);
}
@@ -308,6 +348,7 @@ static ScreenSettings* Settings_defaultScreens(Settings* this) {
const ScreenDefaults* defaults = &Platform_defaultScreens[i];
Settings_newScreen(this, defaults);
}
+ Platform_defaultDynamicScreens(this);
return this->screens[0];
}
@@ -505,6 +546,11 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
} else if (String_eq(option[0], ".all_branches_collapsed")) {
if (screen)
screen->allBranchesCollapsed = atoi(option[1]);
+ } else if (String_eq(option[0], ".dynamic")) {
+ if (screen) {
+ free_and_xStrdup(&screen->dynamic, option[1]);
+ Platform_addDynamicScreen(screen);
+ }
}
String_freeArray(option);
}
@@ -520,11 +566,13 @@ static void writeFields(FILE* fd, const ProcessField* fields, Hashtable* columns
const char* sep = "";
for (unsigned int i = 0; fields[i]; i++) {
if (fields[i] < LAST_PROCESSFIELD && byName) {
- const char* pName = toFieldName(columns, fields[i]);
+ const char* pName = toFieldName(columns, fields[i], NULL);
fprintf(fd, "%s%s", sep, pName);
} else if (fields[i] >= LAST_PROCESSFIELD && byName) {
- const char* pName = toFieldName(columns, fields[i]);
- fprintf(fd, " Dynamic(%s)", pName);
+ bool enabled;
+ const char* pName = toFieldName(columns, fields[i], &enabled);
+ if (enabled)
+ fprintf(fd, "%sDynamic(%s)", sep, pName);
} else {
// This "-1" is for compatibility with the older enum format.
fprintf(fd, "%s%d", sep, (int) fields[i] - 1);
@@ -544,26 +592,41 @@ static void writeList(FILE* fd, char** list, int len, char separator) {
}
static void writeMeters(const Settings* this, FILE* fd, char separator, unsigned int column) {
- writeList(fd, this->hColumns[column].names, this->hColumns[column].len, separator);
+ if (this->hColumns[column].len) {
+ writeList(fd, this->hColumns[column].names, this->hColumns[column].len, separator);
+ } else {
+ fputc('!', fd);
+ fputc(separator, fd);
+ }
}
static void writeMeterModes(const Settings* this, FILE* fd, char separator, unsigned int column) {
- const char* sep = "";
- for (size_t i = 0; i < this->hColumns[column].len; i++) {
- fprintf(fd, "%s%d", sep, this->hColumns[column].modes[i]);
- sep = " ";
+ if (this->hColumns[column].len) {
+ const char* sep = "";
+ for (size_t i = 0; i < this->hColumns[column].len; i++) {
+ fprintf(fd, "%s%d", sep, this->hColumns[column].modes[i]);
+ sep = " ";
+ }
+ } else {
+ fputc('!', fd);
}
+
fputc(separator, fd);
}
int Settings_write(const Settings* this, bool onCrash) {
FILE* fd;
char separator;
+ char* tmpFilename = NULL;
if (onCrash) {
fd = stderr;
separator = ';';
} else {
- fd = fopen(this->filename, "w");
+ xAsprintf(&tmpFilename, "%s.tmp.XXXXXX", this->filename);
+ int fdtmp = mkstemp(tmpFilename);
+ if (fdtmp == -1)
+ return -errno;
+ fd = fdopen(fdtmp, "w");
if (fd == NULL)
return -errno;
separator = '\n';
@@ -639,12 +702,23 @@ int Settings_write(const Settings* this, bool onCrash) {
for (unsigned int i = 0; i < this->nScreens; i++) {
ScreenSettings* ss = this->screens[i];
- fprintf(fd, "screen:%s=", ss->name);
+ const char* sortKey = toFieldName(this->dynamicColumns, ss->sortKey, NULL);
+ const char* treeSortKey = toFieldName(this->dynamicColumns, ss->treeSortKey, NULL);
+
+ fprintf(fd, "screen:%s=", ss->heading);
writeFields(fd, ss->fields, this->dynamicColumns, true, separator);
- printSettingString(".sort_key", toFieldName(this->dynamicColumns, ss->sortKey));
- printSettingString(".tree_sort_key", toFieldName(this->dynamicColumns, ss->treeSortKey));
+ if (ss->dynamic) {
+ printSettingString(".dynamic", ss->dynamic);
+ if (ss->sortKey && ss->sortKey != PID)
+ fprintf(fd, "%s=Dynamic(%s)%c", ".sort_key", sortKey, separator);
+ if (ss->treeSortKey && ss->treeSortKey != PID)
+ fprintf(fd, "%s=Dynamic(%s)%c", ".tree_sort_key", treeSortKey, separator);
+ } else {
+ printSettingString(".sort_key", sortKey);
+ printSettingString(".tree_sort_key", treeSortKey);
+ printSettingInteger(".tree_view_always_by_pid", ss->treeViewAlwaysByPID);
+ }
printSettingInteger(".tree_view", ss->treeView);
- printSettingInteger(".tree_view_always_by_pid", ss->treeViewAlwaysByPID);
printSettingInteger(".sort_direction", ss->direction);
printSettingInteger(".tree_sort_direction", ss->treeDirection);
printSettingInteger(".all_branches_collapsed", ss->allBranchesCollapsed);
@@ -664,13 +738,20 @@ int Settings_write(const Settings* this, bool onCrash) {
if (fclose(fd) != 0)
r = r ? r : -errno;
+ if (r == 0)
+ r = (rename(tmpFilename, this->filename) == -1) ? -errno : 0;
+
+ free(tmpFilename);
+
return r;
}
-Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns) {
+Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* dynamicScreens) {
Settings* this = xCalloc(1, sizeof(Settings));
+ this->dynamicScreens = dynamicScreens;
this->dynamicColumns = dynamicColumns;
+ this->dynamicMeters = dynamicMeters;
this->hLayout = HF_TWO_50_50;
this->hColumns = xCalloc(HeaderLayout_getColumns(this->hLayout), sizeof(MeterColumnSetting));

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