From ece89b8df0db61b8caaf53679afbe00e1c2ef22f Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sat, 27 Jan 2018 23:29:58 -0200 Subject: Begin add supporting for multiple screens --- CRT.c | 7 ++ CRT.h | 1 + CategoriesPanel.c | 9 +- Makefile.am | 4 +- ScreensPanel.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ScreensPanel.h | 39 +++++++++ Settings.c | 80 +++++++++++++++-- Settings.h | 3 + 8 files changed, 386 insertions(+), 11 deletions(-) create mode 100644 ScreensPanel.c create mode 100644 ScreensPanel.h diff --git a/CRT.c b/CRT.c index 676c5509..43ac86b4 100644 --- a/CRT.c +++ b/CRT.c @@ -128,6 +128,7 @@ typedef enum ColorElements_ { CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, + PANEL_EDIT, LAST_COLORELEMENT } ColorElements; @@ -232,6 +233,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = ColorPair(Magenta,Black), [CPU_STEAL] = ColorPair(Cyan,Black), [CPU_GUEST] = ColorPair(Cyan,Black), + [PANEL_EDIT] = ColorPair(White,Blue), }, [COLORSCHEME_MONOCHROME] = { [RESET_COLOR] = A_NORMAL, @@ -291,6 +293,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = A_BOLD, [CPU_STEAL] = A_REVERSE, [CPU_GUEST] = A_REVERSE, + [PANEL_EDIT] = A_BOLD, }, [COLORSCHEME_BLACKONWHITE] = { [RESET_COLOR] = ColorPair(Black,White), @@ -350,6 +353,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = ColorPair(Blue,White), [CPU_STEAL] = ColorPair(Cyan,White), [CPU_GUEST] = ColorPair(Cyan,White), + [PANEL_EDIT] = ColorPair(White,Blue), }, [COLORSCHEME_LIGHTTERMINAL] = { [RESET_COLOR] = ColorPair(Black,Black), @@ -409,6 +413,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = ColorPair(Blue,Black), [CPU_STEAL] = ColorPair(Black,Black), [CPU_GUEST] = ColorPair(Black,Black), + [PANEL_EDIT] = ColorPair(White,Blue), }, [COLORSCHEME_MIDNIGHT] = { [RESET_COLOR] = ColorPair(White,Blue), @@ -468,6 +473,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = ColorPair(Black,Blue), [CPU_STEAL] = ColorPair(White,Blue), [CPU_GUEST] = ColorPair(White,Blue), + [PANEL_EDIT] = ColorPair(White,Blue), }, [COLORSCHEME_BLACKNIGHT] = { [RESET_COLOR] = ColorPair(Cyan,Black), @@ -527,6 +533,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [CPU_SOFTIRQ] = ColorPair(Blue,Black), [CPU_STEAL] = ColorPair(Cyan,Black), [CPU_GUEST] = ColorPair(Cyan,Black), + [PANEL_EDIT] = ColorPair(White,Cyan), }, [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. }; diff --git a/CRT.h b/CRT.h index 6825fff6..2afacfbb 100644 --- a/CRT.h +++ b/CRT.h @@ -116,6 +116,7 @@ typedef enum ColorElements_ { CPU_SOFTIRQ, CPU_STEAL, CPU_GUEST, + PANEL_EDIT, LAST_COLORELEMENT } ColorElements; diff --git a/CategoriesPanel.c b/CategoriesPanel.c index 437f1a7b..64e9933a 100644 --- a/CategoriesPanel.c +++ b/CategoriesPanel.c @@ -11,6 +11,7 @@ in the source distribution for its full text. #include "MetersPanel.h" #include "DisplayOptionsPanel.h" #include "ColumnsPanel.h" +#include "ScreensPanel.h" #include "ColorsPanel.h" #include "AvailableColumnsPanel.h" @@ -64,9 +65,11 @@ static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) { ScreenManager_add(this->scr, colors, -1); } -static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) { +static void CategoriesPanel_makeScreensPage(CategoriesPanel* this) { + Panel* screens = (Panel*) ScreensPanel_new(this->settings); Panel* columns = (Panel*) ColumnsPanel_new(this->settings); Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns); + ScreenManager_add(this->scr, screens, 20); ScreenManager_add(this->scr, columns, 20); ScreenManager_add(this->scr, availableColumns, -1); } @@ -118,7 +121,7 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) { CategoriesPanel_makeColorsPage(this); break; case 3: - CategoriesPanel_makeColumnsPage(this); + CategoriesPanel_makeScreensPage(this); break; } } @@ -147,6 +150,6 @@ CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Hea Panel_add(super, (Object*) ListItem_new("Meters", 0)); Panel_add(super, (Object*) ListItem_new("Display options", 0)); Panel_add(super, (Object*) ListItem_new("Colors", 0)); - Panel_add(super, (Object*) ListItem_new("Columns", 0)); + Panel_add(super, (Object*) ListItem_new("Screens", 0)); return this; } diff --git a/Makefile.am b/Makefile.am index e033c35d..79280998 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c MainPanel.c \ DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ -SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \ +SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c ScreensPanel.c \ TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \ InfoScreen.c XAlloc.c @@ -31,7 +31,7 @@ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ CPUMeter.h CRT.h MainPanel.h DisplayOptionsPanel.h FunctionBar.h \ Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \ -ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \ +ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h ScreensPanel.h \ TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \ AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \ EnvScreen.h InfoScreen.h XAlloc.h diff --git a/ScreensPanel.c b/ScreensPanel.c new file mode 100644 index 00000000..6c88035a --- /dev/null +++ b/ScreensPanel.c @@ -0,0 +1,254 @@ +/* +htop - ScreensPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ScreensPanel.h" +#include "Platform.h" + +#include "StringUtils.h" +#include "ListItem.h" +#include "CRT.h" + +#include +#include +#include +#include + +/*{ +#include "Panel.h" +#include "Settings.h" + +#ifndef SCREEN_NAME_LEN +#define SCREEN_NAME_LEN 20 +#endif + +typedef struct ScreensPanel_ { + Panel super; + + Settings* settings; + char buffer[SCREEN_NAME_LEN + 1]; + char* saved; + int cursor; + bool moving; + bool renaming; +} ScreensPanel; + +}*/ + +static const char* const ScreensFunctions[] = {" ", "Rename", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; + +static void ScreensPanel_delete(Object* object) { + Panel* super = (Panel*) object; + ScreensPanel* this = (ScreensPanel*) object; + Panel_done(super); + free(this); +} + +static HandlerResult ScreensPanel_eventHandlerRenaming(Panel* super, int ch) { + ScreensPanel* const this = (ScreensPanel*) super; + + //ListItem* item = (ListItem*)Panel_getSelected(super); + if (ch >= 32 && ch < 127 && ch != 61 && ch != 22) { + if (this->cursor < SCREEN_NAME_LEN - 1) { + this->buffer[this->cursor] = ch; + this->cursor++; + super->selectedLen = strlen(this->buffer); + Panel_setCursorToSelection(super); + } + } else { + switch(ch) { + case 127: + case KEY_BACKSPACE: + { + if (this->cursor > 0) { + this->cursor--; + this->buffer[this->cursor] = '\0'; + super->selectedLen = strlen(this->buffer); + Panel_setCursorToSelection(super); + } + break; + } + case 0x0a: + case 0x0d: + case KEY_ENTER: + { + ListItem* item = (ListItem*) Panel_getSelected(super); + free(this->saved); + item->value = xStrdup(this->buffer); + this->renaming = false; + super->cursorOn = false; + Panel_setSelectionColor(super, CRT_colors[PANEL_SELECTION_FOCUS]); + break; + } + case 27: // Esc + { + ListItem* item = (ListItem*) Panel_getSelected(super); + item->value = this->saved; + this->renaming = false; + super->cursorOn = false; + Panel_setSelectionColor(super, CRT_colors[PANEL_SELECTION_FOCUS]); + break; + } + } + } + ScreensPanel_update(super); + return HANDLED; +} + +void startRenaming(Panel* super) { + ScreensPanel* const this = (ScreensPanel*) super; + + ListItem* item = (ListItem*) Panel_getSelected(super); + this->renaming = true; + super->cursorOn = true; + char* name = item->value; + this->saved = name; + strncpy(this->buffer, name, SCREEN_NAME_LEN); + this->buffer[SCREEN_NAME_LEN] = '\0'; + this->cursor = strlen(this->buffer); + item->value = this->buffer; + Panel_setSelectionColor(super, CRT_colors[PANEL_EDIT]); + super->selectedLen = strlen(this->buffer); + Panel_setCursorToSelection(super); +} + +static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) { + ScreensPanel* const this = (ScreensPanel*) super; + + int selected = Panel_getSelectedIndex(super); + HandlerResult result = IGNORED; + switch(ch) { + case 0x0a: + case 0x0d: + case KEY_ENTER: + case KEY_MOUSE: + case KEY_RECLICK: + { + this->moving = !(this->moving); + Panel_setSelectionColor(super, this->moving ? CRT_colors[PANEL_SELECTION_FOLLOW] : CRT_colors[PANEL_SELECTION_FOCUS]); + ((ListItem*)Panel_getSelected(super))->moving = this->moving; + result = HANDLED; + break; + } + case KEY_F(2): + case 0x12: /* Ctrl+R */ + { + startRenaming(super); + result = HANDLED; + break; + } + case KEY_F(5): + case 0x0e: /* Ctrl+N */ + { + ListItem* item = ListItem_new("", 0); + int idx = Panel_getSelectedIndex(super); + Panel_insert(super, idx + 1, (Object*) item); + Panel_setSelected(super, idx + 1); + startRenaming(super); + result = HANDLED; + break; + } + case KEY_UP: + { + if (!this->moving) { + break; + } + /* else fallthrough */ + } + case KEY_F(7): + case '[': + case '-': + { + Panel_moveSelectedUp(super); + result = HANDLED; + break; + } + case KEY_DOWN: + { + if (!this->moving) { + break; + } + /* else fallthrough */ + } + case KEY_F(8): + case ']': + case '+': + { + Panel_moveSelectedDown(super); + result = HANDLED; + break; + } + case KEY_F(9): + //case KEY_DC: + { + Panel_remove(super, selected); + result = HANDLED; + break; + } + default: + { + if (ch < 255 && isalpha(ch)) + result = Panel_selectByTyping(super, ch); + if (result == BREAK_LOOP) + result = IGNORED; + break; + } + } + if (result == HANDLED) + ScreensPanel_update(super); + return result; +} + +static HandlerResult ScreensPanel_eventHandler(Panel* super, int ch) { + ScreensPanel* const this = (ScreensPanel*) super; + + if (this->renaming) { + return ScreensPanel_eventHandlerRenaming(super, ch); + } else { + return ScreensPanel_eventHandlerNormal(super, ch); + } +} + +PanelClass ScreensPanel_class = { + .super = { + .extends = Class(Panel), + .delete = ScreensPanel_delete + }, + .eventHandler = ScreensPanel_eventHandler +}; + +ScreensPanel* ScreensPanel_new(Settings* settings) { + ScreensPanel* this = AllocThis(ScreensPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(ScreensFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + this->settings = settings; + this->moving = false; + this->renaming = false; + super->cursorOn = false; + this->cursor = 0; + Panel_setHeader(super, "Screens"); + + char** screens = this->settings->screens; + for (; *screens; screens++) { + char* name = *screens; + Panel_add(super, (Object*) ListItem_new(name, 0)); + } + return this; +} + +void ScreensPanel_update(Panel* super) { + ScreensPanel* this = (ScreensPanel*) super; + int size = Panel_size(super); + this->settings->changed = true; + this->settings->screens = xRealloc(this->settings->screens, sizeof(char*) * (size+1)); + for (int i = 0; i < size; i++) { + char* name = ((ListItem*) Panel_get(super, i))->value; + this->settings->screens[i] = xStrdup(name); + } + this->settings->screens[size] = NULL; +} diff --git a/ScreensPanel.h b/ScreensPanel.h new file mode 100644 index 00000000..35842a95 --- /dev/null +++ b/ScreensPanel.h @@ -0,0 +1,39 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_ScreensPanel +#define HEADER_ScreensPanel +/* +htop - ScreensPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" +#include "Settings.h" + +#ifndef SCREEN_NAME_LEN +#define SCREEN_NAME_LEN 20 +#endif + +typedef struct ScreensPanel_ { + Panel super; + + Settings* settings; + char buffer[SCREEN_NAME_LEN + 1]; + char* saved; + int cursor; + bool moving; + bool renaming; +} ScreensPanel; + + +void startRenaming(Panel* super); + +extern PanelClass ScreensPanel_class; + +ScreensPanel* ScreensPanel_new(Settings* settings); + +void ScreensPanel_update(Panel* super); + +#endif diff --git a/Settings.c b/Settings.c index fdef9566..3de74814 100644 --- a/Settings.c +++ b/Settings.c @@ -34,6 +34,9 @@ typedef struct Settings_ { MeterColumnSettings columns[2]; + char** screens; + int nScreens; + ProcessField* fields; int flags; int colorScheme; @@ -68,6 +71,53 @@ typedef struct Settings_ { }*/ +static void writeList(FILE* fd, char** list, int len) { + const char* sep = ""; + for (int i = 0; i < len; i++) { + fprintf(fd, "%s%s", sep, list[i]); + sep = " "; + } + fprintf(fd, "\n"); +} + +static char** readQuotedList(char* line, int* size) { + *size = 0; + char** list = xCalloc(sizeof(char*), 1); + int start = 0; + for (;;) { + while (line[start] && line[start] == ' ') { + start++; + } + if (line[start] != '"') { + break; + } + start++; + int close = start; + while (line[close] && line[close] != '"') { + close++; + } + int len = close - start; + char* item = xMalloc(len + 1); + strncpy(item, line + start, len); + item[len] = '\0'; + list[*size] = item; + (*size)++; + list = xRealloc(list, sizeof(char*) * (*size + 1)); + start = close + 1; + } + list[*size] = NULL; + return list; +} + +static void writeQuotedList(FILE* fd, char** list, int len) { + const char* sep = ""; + for (int i = 0; i < len; i++) { + fprintf(fd, "%s\"%s\"", sep, list[i]); + sep = " "; + } + fprintf(fd, "\n"); +} + void Settings_delete(Settings* this) { free(this->filename); free(this->fields); @@ -75,6 +125,7 @@ void Settings_delete(Settings* this) { String_freeArray(this->columns[i].names); free(this->columns[i].modes); } + String_freeArray(this->screens); free(this); } @@ -86,6 +137,12 @@ static void Settings_readMeters(Settings* this, char* line, int column) { this->columns[column].names = ids; } +static void Settings_readScreens(Settings* this, char* line) { + char* trim = String_trim(line); + this->screens = readQuotedList(trim, &(this->nScreens)); + free(trim); +} + static void Settings_readMeterModes(Settings* this, char* line, int column) { char* trim = String_trim(line); int nIds; @@ -143,6 +200,13 @@ static void Settings_defaultMeters(Settings* this) { this->columns[1].modes[r++] = TEXT_METERMODE; } +static void Settings_defaultScreens(Settings* this) { + this->screens = xMalloc(sizeof(char*) * 3); + this->screens[0] = xStrdup("Overview"); + this->screens[1] = xStrdup("I/O"); + this->screens[2] = NULL; +} + static void readFields(ProcessField* fields, int* flags, const char* line) { char* trim = String_trim(line); int nIds; @@ -242,10 +306,15 @@ static bool Settings_read(Settings* this, const char* fileName) { } else if (String_eq(option[0], "right_meter_modes")) { Settings_readMeterModes(this, option[1], 1); readMeters = true; + } else if (String_eq(option[0], "screens")) { + Settings_readScreens(this, option[1]); } String_freeArray(option); } fclose(fd); + if (!this->screens) { + Settings_defaultScreens(this); + } if (!readMeters) { Settings_defaultMeters(this); } @@ -264,12 +333,7 @@ static void writeFields(FILE* fd, ProcessField* fields, const char* name) { } static void writeMeters(Settings* this, FILE* fd, int column) { - const char* sep = ""; - for (int i = 0; i < this->columns[column].len; i++) { - fprintf(fd, "%s%s", sep, this->columns[column].names[i]); - sep = " "; - } - fprintf(fd, "\n"); + writeList(fd, this->columns[column].names, this->columns[column].len); } static void writeMeterModes(Settings* this, FILE* fd, int column) { @@ -318,6 +382,9 @@ bool Settings_write(Settings* this) { 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); + if (this->nScreens > 0) { + fprintf(fd, "screens="); writeQuotedList(fd, this->screens, this->nScreens); + } fclose(fd); return true; } @@ -407,6 +474,7 @@ Settings* Settings_new(int cpuCount) { free(systemSettings); if (!ok) { Settings_defaultMeters(this); + Settings_defaultScreens(this); this->hideKernelThreads = true; this->highlightMegabytes = true; this->highlightThreads = true; diff --git a/Settings.h b/Settings.h index d9dc0683..aed438eb 100644 --- a/Settings.h +++ b/Settings.h @@ -25,6 +25,9 @@ typedef struct Settings_ { MeterColumnSettings columns[2]; + char** screens; + int nScreens; + ProcessField* fields; int flags; int colorScheme; -- cgit v1.2.3