2012-11-10 00:31:37 +00:00
|
|
|
/*
|
|
|
|
htop - IncSet.c
|
|
|
|
(C) 2005-2012 Hisham H. Muhammad
|
2020-10-05 07:51:32 +00:00
|
|
|
Released under the GNU GPLv2, see the COPYING file
|
2012-11-10 00:31:37 +00:00
|
|
|
in the source distribution for its full text.
|
|
|
|
*/
|
|
|
|
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "config.h" // IWYU pragma: keep
|
|
|
|
|
2012-11-10 00:31:37 +00:00
|
|
|
#include "IncSet.h"
|
2020-10-14 18:21:09 +00:00
|
|
|
|
2020-09-19 11:55:23 +00:00
|
|
|
#include <ctype.h>
|
2012-11-10 00:31:37 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "CRT.h"
|
|
|
|
#include "ListItem.h"
|
|
|
|
#include "Object.h"
|
|
|
|
#include "ProvideCurses.h"
|
|
|
|
#include "XUtils.h"
|
|
|
|
|
2012-11-10 00:31:37 +00:00
|
|
|
|
|
|
|
static void IncMode_reset(IncMode* mode) {
|
|
|
|
mode->index = 0;
|
|
|
|
mode->buffer[0] = 0;
|
|
|
|
}
|
|
|
|
|
2018-11-03 19:59:55 +00:00
|
|
|
void IncSet_reset(IncSet* this, IncType type) {
|
|
|
|
IncMode_reset(&this->modes[type]);
|
|
|
|
}
|
|
|
|
|
2020-12-23 17:59:51 +00:00
|
|
|
static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL};
|
|
|
|
static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "};
|
|
|
|
static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR};
|
2012-11-10 00:31:37 +00:00
|
|
|
|
|
|
|
static inline void IncMode_initSearch(IncMode* search) {
|
|
|
|
memset(search, 0, sizeof(IncMode));
|
|
|
|
search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents);
|
|
|
|
search->isFilter = false;
|
|
|
|
}
|
|
|
|
|
2017-07-23 02:41:19 +00:00
|
|
|
static const char* const filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL};
|
|
|
|
static const char* const filterKeys[] = {"Enter", "Esc", " "};
|
2020-12-20 15:58:37 +00:00
|
|
|
static const int filterEvents[] = {13, 27, ERR};
|
2012-11-10 00:31:37 +00:00
|
|
|
|
|
|
|
static inline void IncMode_initFilter(IncMode* filter) {
|
|
|
|
memset(filter, 0, sizeof(IncMode));
|
|
|
|
filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents);
|
|
|
|
filter->isFilter = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void IncMode_done(IncMode* mode) {
|
2015-03-23 18:26:56 +00:00
|
|
|
FunctionBar_delete(mode->bar);
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IncSet* IncSet_new(FunctionBar* bar) {
|
2020-12-16 20:46:11 +00:00
|
|
|
IncSet* this = xMalloc(sizeof(IncSet));
|
2012-11-10 00:31:37 +00:00
|
|
|
IncMode_initSearch(&(this->modes[INC_SEARCH]));
|
|
|
|
IncMode_initFilter(&(this->modes[INC_FILTER]));
|
|
|
|
this->active = NULL;
|
|
|
|
this->defaultBar = bar;
|
2020-12-16 20:46:11 +00:00
|
|
|
this->filtering = false;
|
|
|
|
this->found = false;
|
2012-11-10 00:31:37 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IncSet_delete(IncSet* this) {
|
|
|
|
IncMode_done(&(this->modes[0]));
|
|
|
|
IncMode_done(&(this->modes[1]));
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void updateWeakPanel(IncSet* this, Panel* panel, Vector* lines) {
|
|
|
|
Object* selected = Panel_getSelected(panel);
|
|
|
|
Panel_prune(panel);
|
|
|
|
if (this->filtering) {
|
|
|
|
int n = 0;
|
|
|
|
const char* incFilter = this->modes[INC_FILTER].buffer;
|
|
|
|
for (int i = 0; i < Vector_size(lines); i++) {
|
|
|
|
ListItem* line = (ListItem*)Vector_get(lines, i);
|
|
|
|
if (String_contains_i(line->value, incFilter)) {
|
|
|
|
Panel_add(panel, (Object*)line);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (selected == (Object*)line) {
|
|
|
|
Panel_setSelected(panel, n);
|
|
|
|
}
|
|
|
|
|
2012-11-10 00:31:37 +00:00
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < Vector_size(lines); i++) {
|
|
|
|
Object* line = Vector_get(lines, i);
|
|
|
|
Panel_add(panel, line);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (selected == line) {
|
|
|
|
Panel_setSelected(panel, i);
|
|
|
|
}
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-05 13:30:06 +00:00
|
|
|
static bool search(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) {
|
2012-11-10 00:31:37 +00:00
|
|
|
int size = Panel_size(panel);
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
|
|
|
|
Panel_setSelected(panel, i);
|
2020-12-16 20:46:11 +00:00
|
|
|
return true;
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-05 13:14:54 +00:00
|
|
|
|
2020-12-16 20:46:11 +00:00
|
|
|
return false;
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
|
2018-11-03 19:59:55 +00:00
|
|
|
static bool IncMode_find(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) {
|
|
|
|
int size = Panel_size(panel);
|
|
|
|
int here = Panel_getSelectedIndex(panel);
|
|
|
|
int i = here;
|
2020-10-31 19:55:36 +00:00
|
|
|
for (;;) {
|
2020-11-01 00:09:51 +00:00
|
|
|
i += step;
|
|
|
|
if (i == size) {
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
if (i == -1) {
|
|
|
|
i = size - 1;
|
|
|
|
}
|
|
|
|
if (i == here) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-11-03 19:59:55 +00:00
|
|
|
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
|
|
|
|
Panel_setSelected(panel, i);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-10 00:31:37 +00:00
|
|
|
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
|
|
|
|
if (ch == ERR)
|
|
|
|
return true;
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2012-11-10 00:31:37 +00:00
|
|
|
IncMode* mode = this->active;
|
|
|
|
int size = Panel_size(panel);
|
2015-03-23 20:04:53 +00:00
|
|
|
bool filterChanged = false;
|
2012-11-10 00:31:37 +00:00
|
|
|
bool doSearch = true;
|
2020-12-23 17:59:51 +00:00
|
|
|
if (ch == KEY_F(3) || ch == KEY_F(15)) {
|
2020-11-01 00:09:51 +00:00
|
|
|
if (size == 0)
|
|
|
|
return true;
|
|
|
|
|
2020-12-23 17:59:51 +00:00
|
|
|
IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
|
2012-11-10 00:31:37 +00:00
|
|
|
doSearch = false;
|
2020-09-11 17:27:56 +00:00
|
|
|
} else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
|
2016-05-05 13:30:06 +00:00
|
|
|
if (mode->index < INCMODE_MAX) {
|
|
|
|
mode->buffer[mode->index] = ch;
|
|
|
|
mode->index++;
|
|
|
|
mode->buffer[mode->index] = 0;
|
|
|
|
if (mode->isFilter) {
|
|
|
|
filterChanged = true;
|
2020-11-01 00:09:51 +00:00
|
|
|
if (mode->index == 1) {
|
|
|
|
this->filtering = true;
|
|
|
|
}
|
2016-05-05 13:30:06 +00:00
|
|
|
}
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
2016-05-05 13:30:06 +00:00
|
|
|
} else if ((ch == KEY_BACKSPACE || ch == 127)) {
|
|
|
|
if (mode->index > 0) {
|
|
|
|
mode->index--;
|
|
|
|
mode->buffer[mode->index] = 0;
|
|
|
|
if (mode->isFilter) {
|
|
|
|
filterChanged = true;
|
|
|
|
if (mode->index == 0) {
|
|
|
|
this->filtering = false;
|
|
|
|
IncMode_reset(mode);
|
|
|
|
}
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
2016-05-05 13:30:06 +00:00
|
|
|
} else {
|
|
|
|
doSearch = false;
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
2015-12-10 06:42:56 +00:00
|
|
|
} else if (ch == KEY_RESIZE) {
|
2020-10-31 21:14:27 +00:00
|
|
|
Panel_resize(panel, COLS, LINES - panel->y - 1);
|
2012-11-10 00:31:37 +00:00
|
|
|
} else {
|
|
|
|
if (mode->isFilter) {
|
2015-03-23 20:04:53 +00:00
|
|
|
filterChanged = true;
|
2012-11-10 00:31:37 +00:00
|
|
|
if (ch == 27) {
|
|
|
|
this->filtering = false;
|
|
|
|
IncMode_reset(mode);
|
|
|
|
}
|
|
|
|
} else {
|
2018-11-03 19:59:55 +00:00
|
|
|
if (ch == 27) {
|
|
|
|
IncMode_reset(mode);
|
|
|
|
}
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
this->active = NULL;
|
2015-03-23 20:04:53 +00:00
|
|
|
Panel_setDefaultBar(panel);
|
2012-11-10 00:31:37 +00:00
|
|
|
doSearch = false;
|
|
|
|
}
|
|
|
|
if (doSearch) {
|
2016-05-05 13:30:06 +00:00
|
|
|
this->found = search(mode, panel, getPanelValue);
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
2015-03-23 20:04:53 +00:00
|
|
|
if (filterChanged && lines) {
|
2012-11-10 00:31:37 +00:00
|
|
|
updateWeakPanel(this, panel, lines);
|
|
|
|
}
|
2015-03-23 20:04:53 +00:00
|
|
|
return filterChanged;
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* IncSet_getListItemValue(Panel* panel, int i) {
|
|
|
|
ListItem* l = (ListItem*) Panel_get(panel, i);
|
2020-11-01 00:09:51 +00:00
|
|
|
return l ? l->value : "";
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
|
2015-03-23 20:04:53 +00:00
|
|
|
void IncSet_activate(IncSet* this, IncType type, Panel* panel) {
|
2012-11-10 00:31:37 +00:00
|
|
|
this->active = &(this->modes[type]);
|
2015-03-23 20:04:53 +00:00
|
|
|
panel->currentBar = this->active->bar;
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 13:14:54 +00:00
|
|
|
void IncSet_drawBar(const IncSet* this) {
|
2015-03-23 20:04:53 +00:00
|
|
|
if (this->active) {
|
2020-12-16 20:46:11 +00:00
|
|
|
FunctionBar_drawExtra(this->active->bar, this->active->buffer, (this->active->isFilter || this->found) ? -1 : CRT_colors[FAILED_SEARCH], true);
|
2015-03-23 20:04:53 +00:00
|
|
|
} else {
|
2020-10-05 13:14:54 +00:00
|
|
|
FunctionBar_draw(this->defaultBar);
|
2015-03-23 20:04:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int IncSet_synthesizeEvent(IncSet* this, int x) {
|
|
|
|
if (this->active) {
|
|
|
|
return FunctionBar_synthesizeEvent(this->active->bar, x);
|
|
|
|
} else {
|
|
|
|
return FunctionBar_synthesizeEvent(this->defaultBar, x);
|
|
|
|
}
|
2012-11-10 00:31:37 +00:00
|
|
|
}
|