2006-03-04 18:16:49 +00:00
|
|
|
/*
|
2006-05-30 13:47:28 +00:00
|
|
|
htop - Panel.c
|
2011-05-26 16:35:07 +00:00
|
|
|
(C) 2004-2011 Hisham H. Muhammad
|
2020-10-05 07:51:32 +00:00
|
|
|
Released under the GNU GPLv2, see the COPYING file
|
2006-03-04 18:16:49 +00:00
|
|
|
in the source distribution for its full text.
|
|
|
|
*/
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
#include "Panel.h"
|
2011-12-26 21:35:57 +00:00
|
|
|
|
2020-09-19 11:55:23 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
#include "CRT.h"
|
2006-07-11 06:13:32 +00:00
|
|
|
#include "ListItem.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "Macros.h"
|
|
|
|
#include "ProvideCurses.h"
|
|
|
|
#include "RichString.h"
|
2020-10-14 18:21:09 +00:00
|
|
|
#include "XUtils.h"
|
2006-03-04 18:16:49 +00:00
|
|
|
|
2011-12-26 21:35:57 +00:00
|
|
|
|
2020-10-05 11:19:50 +00:00
|
|
|
const PanelClass Panel_class = {
|
2012-12-05 15:12:20 +00:00
|
|
|
.super = {
|
|
|
|
.extends = Class(Object),
|
|
|
|
.delete = Panel_delete
|
|
|
|
},
|
2015-03-25 02:12:43 +00:00
|
|
|
.eventHandler = Panel_selectByTyping,
|
2012-12-05 15:12:20 +00:00
|
|
|
};
|
|
|
|
|
2021-01-02 22:51:53 +00:00
|
|
|
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
|
2006-05-30 13:47:28 +00:00
|
|
|
Panel* this;
|
2016-02-02 14:53:02 +00:00
|
|
|
this = xMalloc(sizeof(Panel));
|
2012-12-05 15:12:20 +00:00
|
|
|
Object_setClass(this, Class(Panel));
|
2015-03-23 18:26:56 +00:00
|
|
|
Panel_init(this, x, y, w, h, type, owner, fuBar);
|
2006-03-04 18:16:49 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_delete(Object* cast) {
|
|
|
|
Panel* this = (Panel*)cast;
|
|
|
|
Panel_done(this);
|
2006-03-04 18:16:49 +00:00
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
2020-10-04 15:55:08 +00:00
|
|
|
void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
|
2006-03-04 18:16:49 +00:00
|
|
|
this->x = x;
|
|
|
|
this->y = y;
|
|
|
|
this->w = w;
|
|
|
|
this->h = h;
|
2015-01-22 01:27:31 +00:00
|
|
|
this->eventHandlerState = NULL;
|
2012-12-05 15:12:20 +00:00
|
|
|
this->items = Vector_new(type, owner, DEFAULT_SIZE);
|
2006-03-04 18:16:49 +00:00
|
|
|
this->scrollV = 0;
|
|
|
|
this->scrollH = 0;
|
|
|
|
this->selected = 0;
|
|
|
|
this->oldSelected = 0;
|
2020-12-21 20:56:26 +00:00
|
|
|
this->selectedLen = 0;
|
2006-03-04 18:16:49 +00:00
|
|
|
this->needsRedraw = true;
|
2020-12-16 20:46:11 +00:00
|
|
|
this->wasFocus = false;
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_beginAllocated(this->header);
|
2015-03-23 18:26:56 +00:00
|
|
|
this->defaultBar = fuBar;
|
|
|
|
this->currentBar = fuBar;
|
2020-12-16 20:46:11 +00:00
|
|
|
this->selectionColorId = PANEL_SELECTION_FOCUS;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_done(Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
2015-01-22 01:27:31 +00:00
|
|
|
free(this->eventHandlerState);
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_delete(this->items);
|
2015-03-23 18:26:56 +00:00
|
|
|
FunctionBar_delete(this->defaultBar);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_end(this->header);
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 20:46:11 +00:00
|
|
|
void Panel_setSelectionColor(Panel* this, ColorElements colorId) {
|
|
|
|
this->selectionColorId = colorId;
|
2015-04-09 18:17:20 +00:00
|
|
|
}
|
|
|
|
|
2010-02-25 01:43:18 +00:00
|
|
|
inline void Panel_setHeader(Panel* this, const char* header) {
|
2020-12-04 13:44:57 +00:00
|
|
|
RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
|
2010-11-22 12:40:20 +00:00
|
|
|
this->needsRedraw = true;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_move(Panel* this, int x, int y) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
|
|
|
this->x = x;
|
|
|
|
this->y = y;
|
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_resize(Panel* this, int w, int h) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
|
|
|
this->w = w;
|
|
|
|
this->h = h;
|
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_prune(Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_prune(this->items);
|
2006-03-04 18:16:49 +00:00
|
|
|
this->scrollV = 0;
|
|
|
|
this->selected = 0;
|
|
|
|
this->oldSelected = 0;
|
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_add(Panel* this, Object* o) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_add(this->items, o);
|
2006-03-04 18:16:49 +00:00
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_insert(Panel* this, int i, Object* o) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_insert(this->items, i, o);
|
2006-03-04 18:16:49 +00:00
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_set(Panel* this, int i, Object* o) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_set(this->items, i, o);
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
Object* Panel_get(Panel* this, int i) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
return Vector_get(this->items, i);
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
Object* Panel_remove(Panel* this, int i) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
|
|
|
this->needsRedraw = true;
|
2006-05-30 13:45:40 +00:00
|
|
|
Object* removed = Vector_remove(this->items, i);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (this->selected > 0 && this->selected >= Vector_size(this->items)) {
|
2006-03-04 18:16:49 +00:00
|
|
|
this->selected--;
|
2020-11-01 00:09:51 +00:00
|
|
|
}
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
return removed;
|
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
Object* Panel_getSelected(Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (Vector_size(this->items) > 0) {
|
2012-03-05 11:18:27 +00:00
|
|
|
return Vector_get(this->items, this->selected);
|
2020-11-01 00:09:51 +00:00
|
|
|
} else {
|
2012-03-05 11:18:27 +00:00
|
|
|
return NULL;
|
2020-11-01 00:09:51 +00:00
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_moveSelectedUp(Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_moveUp(this->items, this->selected);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (this->selected > 0) {
|
2006-03-04 18:16:49 +00:00
|
|
|
this->selected--;
|
2020-11-01 00:09:51 +00:00
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_moveSelectedDown(Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
Vector_moveDown(this->items, this->selected);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (this->selected + 1 < Vector_size(this->items)) {
|
2006-03-04 18:16:49 +00:00
|
|
|
this->selected++;
|
2020-11-01 00:09:51 +00:00
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2021-01-05 22:42:55 +00:00
|
|
|
int Panel_getSelectedIndex(const Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
|
|
|
return this->selected;
|
|
|
|
}
|
|
|
|
|
2021-01-05 22:42:55 +00:00
|
|
|
int Panel_size(const Panel* this) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2006-05-30 13:45:40 +00:00
|
|
|
return Vector_size(this->items);
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-05-30 13:47:28 +00:00
|
|
|
void Panel_setSelected(Panel* this, int selected) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2015-08-27 22:14:25 +00:00
|
|
|
int size = Vector_size(this->items);
|
|
|
|
if (selected >= size) {
|
2015-11-02 15:33:22 +00:00
|
|
|
selected = size - 1;
|
2015-08-27 22:14:25 +00:00
|
|
|
}
|
2020-11-01 00:09:51 +00:00
|
|
|
if (selected < 0) {
|
2014-05-03 21:08:46 +00:00
|
|
|
selected = 0;
|
2020-11-01 00:09:51 +00:00
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
this->selected = selected;
|
2012-12-05 15:12:20 +00:00
|
|
|
if (Panel_eventHandlerFn(this)) {
|
2015-03-25 02:12:43 +00:00
|
|
|
Panel_eventHandler(this, EVENT_SET_SELECTED);
|
2008-03-05 06:54:30 +00:00
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
2020-10-31 22:28:02 +00:00
|
|
|
void Panel_splice(Panel* this, Vector* from) {
|
2020-08-26 00:15:00 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
assert (from != NULL);
|
|
|
|
|
|
|
|
Vector_splice(this->items, from);
|
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
2020-12-28 22:26:14 +00:00
|
|
|
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
int size = Vector_size(this->items);
|
2006-03-04 18:16:49 +00:00
|
|
|
int scrollH = this->scrollH;
|
2015-01-22 01:27:31 +00:00
|
|
|
int y = this->y;
|
|
|
|
int x = this->x;
|
|
|
|
int h = this->h;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
2020-12-28 22:26:14 +00:00
|
|
|
if (hideFunctionBar)
|
|
|
|
h++;
|
|
|
|
|
2020-12-22 16:12:38 +00:00
|
|
|
const int header_attr = focus
|
|
|
|
? CRT_colors[PANEL_HEADER_FOCUS]
|
|
|
|
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
|
|
|
if (force_redraw) {
|
|
|
|
if (Panel_printHeaderFn(this))
|
|
|
|
Panel_printHeader(this);
|
|
|
|
else
|
|
|
|
RichString_setAttr(&this->header, header_attr);
|
|
|
|
}
|
2010-11-22 12:40:20 +00:00
|
|
|
int headerLen = RichString_sizeVal(this->header);
|
|
|
|
if (headerLen > 0) {
|
2020-12-22 16:12:38 +00:00
|
|
|
attrset(header_attr);
|
2006-03-04 18:16:49 +00:00
|
|
|
mvhline(y, x, ' ', this->w);
|
2010-11-22 12:40:20 +00:00
|
|
|
if (scrollH < headerLen) {
|
2008-03-09 02:33:23 +00:00
|
|
|
RichString_printoffnVal(this->header, y, x, scrollH,
|
2020-09-09 06:56:04 +00:00
|
|
|
MINIMUM(headerLen - scrollH, this->w));
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
|
|
|
y++;
|
2021-01-01 21:06:26 +00:00
|
|
|
h--;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
// ensure scroll area is on screen
|
|
|
|
if (this->scrollV < 0) {
|
|
|
|
this->scrollV = 0;
|
|
|
|
this->needsRedraw = true;
|
2021-01-30 22:45:00 +00:00
|
|
|
} else if (this->scrollV > size - h) {
|
|
|
|
this->scrollV = MAXIMUM(size - h, 0);
|
2015-01-22 01:27:31 +00:00
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
// ensure selection is on screen
|
|
|
|
if (this->selected < this->scrollV) {
|
|
|
|
this->scrollV = this->selected;
|
|
|
|
this->needsRedraw = true;
|
|
|
|
} else if (this->selected >= this->scrollV + h) {
|
|
|
|
this->scrollV = this->selected - h + 1;
|
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int first = this->scrollV;
|
2020-09-09 06:56:04 +00:00
|
|
|
int upTo = MINIMUM(first + h, size);
|
2015-01-22 01:27:31 +00:00
|
|
|
|
2015-04-09 18:17:20 +00:00
|
|
|
int selectionColor = focus
|
2020-12-16 20:46:11 +00:00
|
|
|
? CRT_colors[this->selectionColorId]
|
2020-10-31 21:14:27 +00:00
|
|
|
: CRT_colors[PANEL_SELECTION_UNFOCUS];
|
2006-03-04 18:16:49 +00:00
|
|
|
|
2020-12-16 20:46:11 +00:00
|
|
|
if (this->needsRedraw || force_redraw) {
|
2015-01-22 01:27:31 +00:00
|
|
|
int line = 0;
|
2020-10-31 19:55:36 +00:00
|
|
|
for (int i = first; line < h && i < upTo; i++) {
|
2021-01-05 22:42:55 +00:00
|
|
|
const Object* itemObj = Vector_get(this->items, i);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_begin(item);
|
2012-12-05 15:12:20 +00:00
|
|
|
Object_display(itemObj, &item);
|
2010-11-22 12:40:20 +00:00
|
|
|
int itemLen = RichString_sizeVal(item);
|
2020-09-09 06:56:04 +00:00
|
|
|
int amt = MINIMUM(itemLen - scrollH, this->w);
|
2020-11-23 15:23:18 +00:00
|
|
|
if (highlightSelected && i == this->selected) {
|
2020-10-31 01:56:16 +00:00
|
|
|
item.highlightAttr = selectionColor;
|
|
|
|
}
|
|
|
|
if (item.highlightAttr) {
|
|
|
|
attrset(item.highlightAttr);
|
|
|
|
RichString_setAttr(&item, item.highlightAttr);
|
2016-06-15 15:45:23 +00:00
|
|
|
this->selectedLen = itemLen;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
mvhline(y + line, x, ' ', this->w);
|
2014-02-27 19:35:22 +00:00
|
|
|
if (amt > 0)
|
2015-01-22 01:27:31 +00:00
|
|
|
RichString_printoffnVal(item, y + line, x, scrollH, amt);
|
2020-10-31 01:56:16 +00:00
|
|
|
if (item.highlightAttr)
|
2014-02-27 19:35:22 +00:00
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_end(item);
|
2015-01-22 01:27:31 +00:00
|
|
|
line++;
|
|
|
|
}
|
|
|
|
while (line < h) {
|
|
|
|
mvhline(y + line, x, ' ', this->w);
|
|
|
|
line++;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2021-01-05 22:42:55 +00:00
|
|
|
const Object* oldObj = Vector_get(this->items, this->oldSelected);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_begin(old);
|
2012-12-05 15:12:20 +00:00
|
|
|
Object_display(oldObj, &old);
|
2010-11-22 12:40:20 +00:00
|
|
|
int oldLen = RichString_sizeVal(old);
|
2021-01-05 22:42:55 +00:00
|
|
|
const Object* newObj = Vector_get(this->items, this->selected);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_begin(new);
|
2012-12-05 15:12:20 +00:00
|
|
|
Object_display(newObj, &new);
|
2010-11-22 12:40:20 +00:00
|
|
|
int newLen = RichString_sizeVal(new);
|
2016-06-15 15:45:23 +00:00
|
|
|
this->selectedLen = newLen;
|
2020-10-31 22:28:02 +00:00
|
|
|
mvhline(y + this->oldSelected - first, x + 0, ' ', this->w);
|
2010-11-22 12:40:20 +00:00
|
|
|
if (scrollH < oldLen)
|
2020-10-31 22:28:02 +00:00
|
|
|
RichString_printoffnVal(old, y + this->oldSelected - first, x,
|
2020-09-09 06:56:04 +00:00
|
|
|
scrollH, MINIMUM(oldLen - scrollH, this->w));
|
2015-04-09 18:17:20 +00:00
|
|
|
attrset(selectionColor);
|
2020-10-31 22:28:02 +00:00
|
|
|
mvhline(y + this->selected - first, x + 0, ' ', this->w);
|
2015-04-09 18:17:20 +00:00
|
|
|
RichString_setAttr(&new, selectionColor);
|
2010-11-22 12:40:20 +00:00
|
|
|
if (scrollH < newLen)
|
2020-10-31 22:28:02 +00:00
|
|
|
RichString_printoffnVal(new, y + this->selected - first, x,
|
2020-09-09 06:56:04 +00:00
|
|
|
scrollH, MINIMUM(newLen - scrollH, this->w));
|
2006-03-04 18:16:49 +00:00
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
2010-11-22 12:40:20 +00:00
|
|
|
RichString_end(new);
|
|
|
|
RichString_end(old);
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
2020-12-16 20:46:11 +00:00
|
|
|
|
|
|
|
if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) {
|
|
|
|
if (Panel_drawFunctionBarFn(this))
|
2020-12-28 22:26:14 +00:00
|
|
|
Panel_drawFunctionBar(this, hideFunctionBar);
|
|
|
|
else if (!hideFunctionBar)
|
2020-12-16 20:46:11 +00:00
|
|
|
FunctionBar_draw(this->currentBar);
|
|
|
|
}
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
this->oldSelected = this->selected;
|
2020-12-16 20:46:11 +00:00
|
|
|
this->wasFocus = focus;
|
|
|
|
this->needsRedraw = false;
|
2006-03-04 18:16:49 +00:00
|
|
|
move(0, 0);
|
|
|
|
}
|
|
|
|
|
2021-01-01 21:06:26 +00:00
|
|
|
static int Panel_headerHeight(const Panel* this) {
|
|
|
|
return RichString_sizeVal(this->header) > 0 ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2009-06-02 04:51:23 +00:00
|
|
|
bool Panel_onKey(Panel* this, int key) {
|
2006-03-04 18:16:49 +00:00
|
|
|
assert (this != NULL);
|
2019-10-31 16:39:12 +00:00
|
|
|
|
2021-01-01 21:06:26 +00:00
|
|
|
const int size = Vector_size(this->items);
|
2020-11-21 16:03:17 +00:00
|
|
|
|
2021-01-01 21:06:26 +00:00
|
|
|
#define PANEL_SCROLL(amount) \
|
|
|
|
do { \
|
|
|
|
this->selected += (amount); \
|
|
|
|
this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \
|
|
|
|
this->needsRedraw = true; \
|
|
|
|
} while (0)
|
2020-11-21 16:03:17 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
switch (key) {
|
|
|
|
case KEY_DOWN:
|
2016-06-15 15:45:23 +00:00
|
|
|
case KEY_CTRL('N'):
|
2009-06-02 04:51:23 +00:00
|
|
|
#ifdef KEY_C_DOWN
|
|
|
|
case KEY_C_DOWN:
|
2020-11-21 16:00:58 +00:00
|
|
|
#endif
|
2015-01-22 01:27:31 +00:00
|
|
|
this->selected++;
|
|
|
|
break;
|
2020-11-21 16:00:58 +00:00
|
|
|
|
|
|
|
case KEY_UP:
|
|
|
|
case KEY_CTRL('P'):
|
2009-06-02 04:51:23 +00:00
|
|
|
#ifdef KEY_C_UP
|
|
|
|
case KEY_C_UP:
|
2020-11-21 16:00:58 +00:00
|
|
|
#endif
|
2015-01-22 01:27:31 +00:00
|
|
|
this->selected--;
|
|
|
|
break;
|
2020-11-21 16:00:58 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_LEFT:
|
2016-06-15 15:45:23 +00:00
|
|
|
case KEY_CTRL('B'):
|
2006-03-04 18:16:49 +00:00
|
|
|
if (this->scrollH > 0) {
|
2020-09-09 06:56:04 +00:00
|
|
|
this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
|
2006-03-04 18:16:49 +00:00
|
|
|
this->needsRedraw = true;
|
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_RIGHT:
|
2016-06-15 15:45:23 +00:00
|
|
|
case KEY_CTRL('F'):
|
2014-02-27 19:35:22 +00:00
|
|
|
this->scrollH += CRT_scrollHAmount;
|
2006-03-04 18:16:49 +00:00
|
|
|
this->needsRedraw = true;
|
2015-01-22 01:27:31 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_PPAGE:
|
2021-01-01 21:06:26 +00:00
|
|
|
PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
|
2015-01-22 01:27:31 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_NPAGE:
|
2021-01-01 21:06:26 +00:00
|
|
|
PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
|
2015-01-22 01:27:31 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2015-08-19 21:55:24 +00:00
|
|
|
case KEY_WHEELUP:
|
2021-01-01 21:06:26 +00:00
|
|
|
PANEL_SCROLL(-CRT_scrollWheelVAmount);
|
2015-08-19 21:55:24 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2015-08-19 21:55:24 +00:00
|
|
|
case KEY_WHEELDOWN:
|
2021-01-01 21:06:26 +00:00
|
|
|
PANEL_SCROLL(+CRT_scrollWheelVAmount);
|
2015-08-19 21:55:24 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_HOME:
|
|
|
|
this->selected = 0;
|
2015-01-22 01:27:31 +00:00
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
case KEY_END:
|
2015-01-22 01:27:31 +00:00
|
|
|
this->selected = size - 1;
|
|
|
|
break;
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2016-06-15 15:45:23 +00:00
|
|
|
case KEY_CTRL('A'):
|
|
|
|
case '^':
|
|
|
|
this->scrollH = 0;
|
2016-06-19 21:05:18 +00:00
|
|
|
this->needsRedraw = true;
|
2016-06-15 15:45:23 +00:00
|
|
|
break;
|
|
|
|
case KEY_CTRL('E'):
|
|
|
|
case '$':
|
2020-09-09 06:56:04 +00:00
|
|
|
this->scrollH = MAXIMUM(this->selectedLen - this->w, 0);
|
2016-06-19 21:05:18 +00:00
|
|
|
this->needsRedraw = true;
|
2016-06-15 15:45:23 +00:00
|
|
|
break;
|
2015-01-22 01:27:31 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-01 21:06:26 +00:00
|
|
|
#undef PANEL_SCROLL
|
2020-11-21 16:03:17 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
// ensure selection within bounds
|
2016-02-18 19:45:04 +00:00
|
|
|
if (this->selected < 0 || size == 0) {
|
2015-01-22 01:27:31 +00:00
|
|
|
this->selected = 0;
|
|
|
|
this->needsRedraw = true;
|
2019-10-31 16:39:12 +00:00
|
|
|
} else if (this->selected >= size) {
|
2015-01-22 01:27:31 +00:00
|
|
|
this->selected = size - 1;
|
|
|
|
this->needsRedraw = true;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
return true;
|
2006-03-04 18:16:49 +00:00
|
|
|
}
|
2011-11-18 06:08:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
|
|
|
|
int size = Panel_size(this);
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
if (!this->eventHandlerState)
|
2016-02-02 14:53:02 +00:00
|
|
|
this->eventHandlerState = xCalloc(100, sizeof(char));
|
2015-01-22 01:27:31 +00:00
|
|
|
char* buffer = this->eventHandlerState;
|
2011-11-18 06:08:56 +00:00
|
|
|
|
2020-11-21 17:02:39 +00:00
|
|
|
if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) {
|
2015-01-22 01:27:31 +00:00
|
|
|
int len = strlen(buffer);
|
2020-11-21 16:04:05 +00:00
|
|
|
if (!len) {
|
|
|
|
if ('/' == ch) {
|
|
|
|
ch = '\001';
|
|
|
|
} else if ('q' == ch) {
|
|
|
|
return BREAK_LOOP;
|
|
|
|
}
|
|
|
|
} else if (1 == len && '\001' == buffer[0]) {
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
2011-11-18 06:08:56 +00:00
|
|
|
if (len < 99) {
|
2015-01-22 01:27:31 +00:00
|
|
|
buffer[len] = ch;
|
|
|
|
buffer[len+1] = '\0';
|
2011-11-18 06:08:56 +00:00
|
|
|
}
|
2020-11-21 16:04:05 +00:00
|
|
|
|
2011-11-18 06:08:56 +00:00
|
|
|
for (int try = 0; try < 2; try++) {
|
2015-01-22 01:27:31 +00:00
|
|
|
len = strlen(buffer);
|
2011-11-18 06:08:56 +00:00
|
|
|
for (int i = 0; i < size; i++) {
|
2020-10-27 10:46:29 +00:00
|
|
|
const char* cur = ((ListItem*) Panel_get(this, i))->value;
|
2011-11-18 06:08:56 +00:00
|
|
|
while (*cur == ' ') cur++;
|
2015-01-22 01:27:31 +00:00
|
|
|
if (strncasecmp(cur, buffer, len) == 0) {
|
2011-11-18 06:08:56 +00:00
|
|
|
Panel_setSelected(this, i);
|
|
|
|
return HANDLED;
|
|
|
|
}
|
|
|
|
}
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
// if current word did not match,
|
|
|
|
// retry considering the character the start of a new word.
|
|
|
|
buffer[0] = ch;
|
|
|
|
buffer[1] = '\0';
|
2011-11-18 06:08:56 +00:00
|
|
|
}
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2011-11-18 06:08:56 +00:00
|
|
|
return HANDLED;
|
|
|
|
} else if (ch != ERR) {
|
2015-01-22 01:27:31 +00:00
|
|
|
buffer[0] = '\0';
|
2011-11-18 06:08:56 +00:00
|
|
|
}
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2011-11-18 06:08:56 +00:00
|
|
|
if (ch == 13) {
|
|
|
|
return BREAK_LOOP;
|
|
|
|
}
|
2020-11-21 16:04:25 +00:00
|
|
|
|
2011-11-18 06:08:56 +00:00
|
|
|
return IGNORED;
|
|
|
|
}
|