Allow typing to select items in various panels (sort, user, signal).

Factored code from the SignalsPanel to apply to all selections from main screen.
Closes feature request #3425304.
This commit is contained in:
Hisham Muhammad 2011-11-05 04:19:47 +00:00
parent 4c4cceee5d
commit e204861de5
8 changed files with 89 additions and 184 deletions

View File

@ -23,7 +23,7 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c DebugMemory.c \
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.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 \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalItem.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \ SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
HostnameMeter.c OpenFilesScreen.c Affinity.c HostnameMeter.c OpenFilesScreen.c Affinity.c
@ -32,7 +32,7 @@ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \ CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.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 \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
ScreenManager.h Settings.h SignalItem.h SignalsPanel.h String.h \ ScreenManager.h Settings.h SignalsPanel.h String.h \
SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \ SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
Process.h AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h Process.h AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h

View File

@ -47,6 +47,7 @@ struct Panel_ {
bool needsRedraw; bool needsRedraw;
RichString header; RichString header;
Panel_EventHandler eventHandler; Panel_EventHandler eventHandler;
char* eventHandlerBuffer;
}; };
}*/ }*/

View File

@ -49,6 +49,7 @@ struct Panel_ {
bool needsRedraw; bool needsRedraw;
RichString header; RichString header;
Panel_EventHandler eventHandler; Panel_EventHandler eventHandler;
char* eventHandlerBuffer;
}; };

View File

@ -1,101 +0,0 @@
/*
htop - SignalItem.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 "SignalItem.h"
#include "String.h"
#include "Object.h"
#include "RichString.h"
#include <string.h>
#include "debug.h"
#define SIGNAL_COUNT 34
/*{
typedef struct Signal_ {
Object super;
const char* name;
int number;
} Signal;
}*/
#ifdef DEBUG
char* SIGNAL_CLASS = "Signal";
#else
#define SIGNAL_CLASS NULL
#endif
static void Signal_delete(Object* cast) {
Signal* this = (Signal*)cast;
assert (this != NULL);
// names are string constants, so we're not deleting them.
free(this);
}
static void Signal_display(Object* cast, RichString* out) {
Signal* this = (Signal*)cast;
assert (this != NULL);
char buffer[31];
snprintf(buffer, 30, "%2d %s", this->number, this->name);
RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer);
}
static Signal* Signal_new(const char* name, int number) {
Signal* this = malloc(sizeof(Signal));
Object_setClass(this, SIGNAL_CLASS);
((Object*)this)->display = Signal_display;
((Object*)this)->delete = Signal_delete;
this->name = name;
this->number = number;
return this;
}
int Signal_getSignalCount() {
return SIGNAL_COUNT;
}
Signal** Signal_getSignalTable() {
Signal** signals = malloc(sizeof(Signal*) * SIGNAL_COUNT);
signals[0] = Signal_new("Cancel", 0);
signals[1] = Signal_new("SIGHUP", 1);
signals[2] = Signal_new("SIGINT", 2);
signals[3] = Signal_new("SIGQUIT", 3);
signals[4] = Signal_new("SIGILL", 4);
signals[5] = Signal_new("SIGTRAP", 5);
signals[6] = Signal_new("SIGABRT", 6);
signals[7] = Signal_new("SIGIOT", 6);
signals[8] = Signal_new("SIGBUS", 7);
signals[9] = Signal_new("SIGFPE", 8);
signals[10] = Signal_new("SIGKILL", 9);
signals[11] = Signal_new("SIGUSR1", 10);
signals[12] = Signal_new("SIGSEGV", 11);
signals[13] = Signal_new("SIGUSR2", 12);
signals[14] = Signal_new("SIGPIPE", 13);
signals[15] = Signal_new("SIGALRM", 14);
signals[16] = Signal_new("SIGTERM", 15);
signals[17] = Signal_new("SIGSTKFLT", 16);
signals[18] = Signal_new("SIGCHLD", 17);
signals[19] = Signal_new("SIGCONT", 18);
signals[20] = Signal_new("SIGSTOP", 19);
signals[21] = Signal_new("SIGTSTP", 20);
signals[22] = Signal_new("SIGTTIN", 21);
signals[23] = Signal_new("SIGTTOU", 22);
signals[24] = Signal_new("SIGURG", 23);
signals[25] = Signal_new("SIGXCPU", 24);
signals[26] = Signal_new("SIGXFSZ", 25);
signals[27] = Signal_new("SIGVTALRM", 26);
signals[28] = Signal_new("SIGPROF", 27);
signals[29] = Signal_new("SIGWINCH", 28);
signals[30] = Signal_new("SIGIO", 29);
signals[31] = Signal_new("SIGPOLL", 29);
signals[32] = Signal_new("SIGPWR", 30);
signals[33] = Signal_new("SIGSYS", 31);
return signals;
}

View File

@ -1,39 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_SignalItem
#define HEADER_SignalItem
/*
htop - SignalItem.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 "String.h"
#include "Object.h"
#include "RichString.h"
#include <string.h>
#include "debug.h"
#define SIGNAL_COUNT 34
typedef struct Signal_ {
Object super;
const char* name;
int number;
} Signal;
#ifdef DEBUG
extern char* SIGNAL_CLASS;
#else
#define SIGNAL_CLASS NULL
#endif
int Signal_getSignalCount();
Signal** Signal_getSignalTable();
#endif

View File

@ -1,7 +1,7 @@
#include "SignalsPanel.h" #include "SignalsPanel.h"
#include "Panel.h" #include "Panel.h"
#include "SignalItem.h" #include "ListItem.h"
#include "RichString.h" #include "RichString.h"
#include "debug.h" #include "debug.h"
@ -13,37 +13,14 @@
typedef struct SignalsPanel_ { typedef struct SignalsPanel_ {
Panel super; Panel super;
ListItem** signals;
int state;
Signal** signals;
} SignalsPanel; } SignalsPanel;
}*/ }*/
static HandlerResult SignalsPanel_eventHandler(Panel* super, int ch) { #ifndef SIGNAL_COUNT
SignalsPanel* this = (SignalsPanel*) super; #define SIGNAL_COUNT 34
#endif
int size = Panel_size(super);
if (ch <= 255 && isdigit(ch)) {
int sgn = ch-48 + this->state;
for (int i = 0; i < size; i++)
if (((Signal*) Panel_get(super, i))->number == sgn) {
Panel_setSelected(super, i);
break;
}
this->state = sgn * 10;
if (this->state > 100)
this->state = 0;
return HANDLED;
} else {
this->state = 0;
}
if (ch == 13) {
return BREAK_LOOP;
}
return IGNORED;
}
static void SignalsPanel_delete(Object* object) { static void SignalsPanel_delete(Object* object) {
Panel* super = (Panel*) object; Panel* super = (Panel*) object;
@ -53,16 +30,53 @@ static void SignalsPanel_delete(Object* object) {
free(this); free(this);
} }
static ListItem** Signal_getSignalTable() {
ListItem** signals = malloc(sizeof(ListItem*) * SIGNAL_COUNT);
signals[0] = ListItem_new(" 0 Cancel", 0);
signals[1] = ListItem_new(" 1 SIGHUP", 1);
signals[2] = ListItem_new(" 2 SIGINT", 2);
signals[3] = ListItem_new(" 3 SIGQUIT", 3);
signals[4] = ListItem_new(" 4 SIGILL", 4);
signals[5] = ListItem_new(" 5 SIGTRAP", 5);
signals[6] = ListItem_new(" 6 SIGABRT", 6);
signals[7] = ListItem_new(" 6 SIGIOT", 6);
signals[8] = ListItem_new(" 7 SIGBUS", 7);
signals[9] = ListItem_new(" 8 SIGFPE", 8);
signals[10] = ListItem_new(" 9 SIGKILL", 9);
signals[11] = ListItem_new("10 SIGUSR1", 10);
signals[12] = ListItem_new("11 SIGSEGV", 11);
signals[13] = ListItem_new("12 SIGUSR2", 12);
signals[14] = ListItem_new("13 SIGPIPE", 13);
signals[15] = ListItem_new("14 SIGALRM", 14);
signals[16] = ListItem_new("15 SIGTERM", 15);
signals[17] = ListItem_new("16 SIGSTKFLT", 16);
signals[18] = ListItem_new("17 SIGCHLD", 17);
signals[19] = ListItem_new("18 SIGCONT", 18);
signals[20] = ListItem_new("19 SIGSTOP", 19);
signals[21] = ListItem_new("20 SIGTSTP", 20);
signals[22] = ListItem_new("21 SIGTTIN", 21);
signals[23] = ListItem_new("22 SIGTTOU", 22);
signals[24] = ListItem_new("23 SIGURG", 23);
signals[25] = ListItem_new("24 SIGXCPU", 24);
signals[26] = ListItem_new("25 SIGXFSZ", 25);
signals[27] = ListItem_new("26 SIGVTALRM", 26);
signals[28] = ListItem_new("27 SIGPROF", 27);
signals[29] = ListItem_new("28 SIGWINCH", 28);
signals[30] = ListItem_new("29 SIGIO", 29);
signals[31] = ListItem_new("29 SIGPOLL", 29);
signals[32] = ListItem_new("30 SIGPWR", 30);
signals[33] = ListItem_new("31 SIGSYS", 31);
return signals;
}
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h) { SignalsPanel* SignalsPanel_new(int x, int y, int w, int h) {
SignalsPanel* this = (SignalsPanel*) malloc(sizeof(SignalsPanel)); SignalsPanel* this = (SignalsPanel*) malloc(sizeof(SignalsPanel));
Panel* super = (Panel*) this; Panel* super = (Panel*) this;
Panel_init(super, x, y, w, h, SIGNAL_CLASS, true); Panel_init(super, x, y, w, h, LISTITEM_CLASS, true);
((Object*)this)->delete = SignalsPanel_delete; ((Object*)this)->delete = SignalsPanel_delete;
this->signals = Signal_getSignalTable(); this->signals = Signal_getSignalTable();
super->eventHandler = SignalsPanel_eventHandler; for(int i = 0; i < SIGNAL_COUNT; i++)
int sigCount = Signal_getSignalCount();
for(int i = 0; i < sigCount; i++)
Panel_set(super, i, (Object*) this->signals[i]); Panel_set(super, i, (Object*) this->signals[i]);
SignalsPanel_reset(this); SignalsPanel_reset(this);
return this; return this;
@ -73,5 +87,4 @@ void SignalsPanel_reset(SignalsPanel* this) {
Panel_setHeader(super, "Send signal:"); Panel_setHeader(super, "Send signal:");
Panel_setSelected(super, 16); // 16th item is SIGTERM Panel_setSelected(super, 16); // 16th item is SIGTERM
this->state = 0;
} }

View File

@ -4,7 +4,7 @@
#define HEADER_SignalsPanel #define HEADER_SignalsPanel
#include "Panel.h" #include "Panel.h"
#include "SignalItem.h" #include "ListItem.h"
#include "RichString.h" #include "RichString.h"
#include "debug.h" #include "debug.h"
@ -15,12 +15,14 @@
typedef struct SignalsPanel_ { typedef struct SignalsPanel_ {
Panel super; Panel super;
ListItem** signals;
int state;
Signal** signals;
} SignalsPanel; } SignalsPanel;
#ifndef SIGNAL_COUNT
#define SIGNAL_COUNT 34
#endif
SignalsPanel* SignalsPanel_new(int x, int y, int w, int h); SignalsPanel* SignalsPanel_new(int x, int y, int w, int h);
void SignalsPanel_reset(SignalsPanel* this); void SignalsPanel_reset(SignalsPanel* this);

38
htop.c
View File

@ -195,15 +195,41 @@ static bool changePriority(Panel* panel, int delta) {
} }
static HandlerResult pickWithEnter(Panel* panel, int ch) { static HandlerResult pickWithEnter(Panel* panel, int ch) {
(void) panel; int size = Panel_size(panel);
if (ch == 13)
if (isalnum(ch)) {
int len = strlen(panel->eventHandlerBuffer);
if (len < 99) {
panel->eventHandlerBuffer[len] = ch;
panel->eventHandlerBuffer[len+1] = '\0';
}
for (int try = 0; try < 2; try++) {
len = strlen(panel->eventHandlerBuffer);
for (int i = 0; i < size; i++) {
char* cur = ((ListItem*) Panel_get(panel, i))->value;
while (*cur == ' ') cur++;
if (strncasecmp(cur, panel->eventHandlerBuffer, len) == 0) {
Panel_setSelected(panel, i);
return HANDLED;
}
}
panel->eventHandlerBuffer[0] = ch;
panel->eventHandlerBuffer[1] = '\0';
}
return HANDLED;
} else if (ch != ERR) {
panel->eventHandlerBuffer[0] = '\0';
}
if (ch == 13) {
return BREAK_LOOP; return BREAK_LOOP;
}
return IGNORED; return IGNORED;
} }
static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) { static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) {
const char* fuKeys[] = {"Enter", "Esc", NULL}; const char* fuKeys[] = {"Enter", "Esc", NULL};
int fuEvents[] = {13, 27}; int fuEvents[] = {13, 27};
list->eventHandlerBuffer = calloc(100, 1);
if (!list->eventHandler) if (!list->eventHandler)
Panel_setEventHandler(list, pickWithEnter); Panel_setEventHandler(list, pickWithEnter);
ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false); ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false);
@ -213,6 +239,8 @@ static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const cha
int ch; int ch;
ScreenManager_run(scr, &panelFocus, &ch); ScreenManager_run(scr, &panelFocus, &ch);
ScreenManager_delete(scr); ScreenManager_delete(scr);
free(list->eventHandlerBuffer);
list->eventHandlerBuffer = NULL;
Panel_move(panel, 0, y); Panel_move(panel, 0, y);
Panel_resize(panel, COLS, LINES-y-1); Panel_resize(panel, COLS, LINES-y-1);
FunctionBar_draw(prevBar, NULL); FunctionBar_draw(prevBar, NULL);
@ -758,7 +786,7 @@ int main(int argc, char** argv) {
const char* fuFunctions[] = {"Send ", "Cancel ", NULL}; const char* fuFunctions[] = {"Send ", "Cancel ", NULL};
Signal* sgn = (Signal*) pickFromVector(panel, killPanel, 15, headerHeight, fuFunctions, defaultBar, header); Signal* sgn = (Signal*) pickFromVector(panel, killPanel, 15, headerHeight, fuFunctions, defaultBar, header);
if (sgn) { if (sgn) {
if (sgn->number != 0) { if (sgn->super.key != 0) {
Panel_setHeader(panel, "Sending..."); Panel_setHeader(panel, "Sending...");
Panel_draw(panel, true); Panel_draw(panel, true);
refresh(); refresh();
@ -766,13 +794,13 @@ int main(int argc, char** argv) {
for (int i = 0; i < Panel_size(panel); i++) { for (int i = 0; i < Panel_size(panel); i++) {
Process* p = (Process*) Panel_get(panel, i); Process* p = (Process*) Panel_get(panel, i);
if (p->tag) { if (p->tag) {
Process_sendSignal(p, sgn->number); Process_sendSignal(p, sgn->super.key);
anyTagged = true; anyTagged = true;
} }
} }
if (!anyTagged) { if (!anyTagged) {
Process* p = (Process*) Panel_getSelected(panel); Process* p = (Process*) Panel_getSelected(panel);
Process_sendSignal(p, sgn->number); Process_sendSignal(p, sgn->super.key);
} }
napms(500); napms(500);
} }