mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-12 12:14:36 +03:00
Sorry about the mega-patch.
This is a work-in-progress, code is currently broken. (Some actions, and notably, the header, are missing.)
This commit is contained in:
179
Panel.c
179
Panel.c
@ -28,9 +28,11 @@ in the source distribution for its full text.
|
||||
typedef struct Panel_ Panel;
|
||||
|
||||
typedef enum HandlerResult_ {
|
||||
HANDLED,
|
||||
IGNORED,
|
||||
BREAK_LOOP
|
||||
HANDLED = 0x00,
|
||||
IGNORED = 0x01,
|
||||
BREAK_LOOP = 0x02,
|
||||
REFRESH = 0x04,
|
||||
RECALCULATE = 0x08,
|
||||
} HandlerResult;
|
||||
|
||||
#define EVENT_SETSELECTED -1
|
||||
@ -54,7 +56,7 @@ struct Panel_ {
|
||||
Vector* items;
|
||||
int selected;
|
||||
int oldSelected;
|
||||
char* eventHandlerBuffer;
|
||||
void* eventHandlerState;
|
||||
int scrollV;
|
||||
short scrollH;
|
||||
bool needsRedraw;
|
||||
@ -102,7 +104,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool
|
||||
this->y = y;
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->eventHandlerBuffer = NULL;
|
||||
this->eventHandlerState = NULL;
|
||||
this->items = Vector_new(type, owner, DEFAULT_SIZE);
|
||||
this->scrollV = 0;
|
||||
this->scrollH = 0;
|
||||
@ -114,7 +116,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool
|
||||
|
||||
void Panel_done(Panel* this) {
|
||||
assert (this != NULL);
|
||||
free(this->eventHandlerBuffer);
|
||||
free(this->eventHandlerState);
|
||||
Vector_delete(this->items);
|
||||
RichString_end(this->header);
|
||||
}
|
||||
@ -246,30 +248,11 @@ void Panel_setSelected(Panel* this, int selected) {
|
||||
void Panel_draw(Panel* this, bool focus) {
|
||||
assert (this != NULL);
|
||||
|
||||
int itemCount = Vector_size(this->items);
|
||||
int size = Vector_size(this->items);
|
||||
int scrollH = this->scrollH;
|
||||
int y = this->y; int x = this->x;
|
||||
int first = this->scrollV;
|
||||
if (itemCount > this->h && first > itemCount - this->h) {
|
||||
first = itemCount - this->h;
|
||||
this->scrollV = first;
|
||||
}
|
||||
int last = MIN(itemCount, first + MIN(itemCount, this->h));
|
||||
if (this->selected < first) {
|
||||
first = this->selected;
|
||||
this->scrollV = first;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
if (this->selected >= last) {
|
||||
last = MIN(itemCount, this->selected + 1);
|
||||
first = last - this->h;
|
||||
this->scrollV = first;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
if (first < 0)
|
||||
first = 0;
|
||||
if (last > itemCount)
|
||||
last = itemCount;
|
||||
int y = this->y;
|
||||
int x = this->x;
|
||||
int h = this->h;
|
||||
|
||||
int headerLen = RichString_sizeVal(this->header);
|
||||
if (headerLen > 0) {
|
||||
@ -285,14 +268,34 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
y++;
|
||||
}
|
||||
|
||||
|
||||
// ensure scroll area is on screen
|
||||
if (this->scrollV < 0) {
|
||||
this->scrollV = 0;
|
||||
this->needsRedraw = true;
|
||||
} else if (this->scrollV >= size) {
|
||||
this->scrollV = MAX(size - 1, 0);
|
||||
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;
|
||||
int upTo = MIN(first + h, size);
|
||||
|
||||
int highlight = focus
|
||||
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
|
||||
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
|
||||
|
||||
if (this->needsRedraw) {
|
||||
|
||||
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
|
||||
int line = 0;
|
||||
for(int i = first; line < h && i < upTo; i++) {
|
||||
Object* itemObj = Vector_get(this->items, i);
|
||||
assert(itemObj); if(!itemObj) continue;
|
||||
RichString_begin(item);
|
||||
@ -304,15 +307,18 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
attrset(highlight);
|
||||
RichString_setAttr(&item, highlight);
|
||||
}
|
||||
mvhline(y + j, x, ' ', this->w);
|
||||
mvhline(y + line, x, ' ', this->w);
|
||||
if (amt > 0)
|
||||
RichString_printoffnVal(item, y+j, x, scrollH, amt);
|
||||
RichString_printoffnVal(item, y + line, x, scrollH, amt);
|
||||
if (selected)
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(item);
|
||||
line++;
|
||||
}
|
||||
while (line < h) {
|
||||
mvhline(y + line, x, ' ', this->w);
|
||||
line++;
|
||||
}
|
||||
for (int i = y + (last - first); i < y + this->h; i++)
|
||||
mvhline(i, x+0, ' ', this->w);
|
||||
this->needsRedraw = false;
|
||||
|
||||
} else {
|
||||
@ -325,15 +331,15 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
RichString_begin(new);
|
||||
Object_display(newObj, &new);
|
||||
int newLen = RichString_sizeVal(new);
|
||||
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
|
||||
mvhline(y+ this->oldSelected - first, x+0, ' ', this->w);
|
||||
if (scrollH < oldLen)
|
||||
RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x,
|
||||
RichString_printoffnVal(old, y+this->oldSelected - first, x,
|
||||
scrollH, MIN(oldLen - scrollH, this->w));
|
||||
attrset(highlight);
|
||||
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
|
||||
mvhline(y+this->selected - first, x+0, ' ', this->w);
|
||||
RichString_setAttr(&new, highlight);
|
||||
if (scrollH < newLen)
|
||||
RichString_printoffnVal(new, y+this->selected - this->scrollV, x,
|
||||
RichString_printoffnVal(new, y+this->selected - first, x,
|
||||
scrollH, MIN(newLen - scrollH, this->w));
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
RichString_end(new);
|
||||
@ -345,38 +351,26 @@ void Panel_draw(Panel* this, bool focus) {
|
||||
|
||||
bool Panel_onKey(Panel* this, int key) {
|
||||
assert (this != NULL);
|
||||
|
||||
int size = Vector_size(this->items);
|
||||
switch (key) {
|
||||
case KEY_DOWN:
|
||||
case KEY_CTRLN:
|
||||
if (this->selected + 1 < Vector_size(this->items))
|
||||
this->selected++;
|
||||
return true;
|
||||
this->selected++;
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_CTRLP:
|
||||
if (this->selected > 0)
|
||||
this->selected--;
|
||||
return true;
|
||||
this->selected--;
|
||||
break;
|
||||
#ifdef KEY_C_DOWN
|
||||
case KEY_C_DOWN:
|
||||
if (this->selected + 1 < Vector_size(this->items)) {
|
||||
this->selected++;
|
||||
if (this->scrollV < Vector_size(this->items) - this->h) {
|
||||
this->scrollV++;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
this->selected++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_C_UP
|
||||
case KEY_C_UP:
|
||||
if (this->selected > 0) {
|
||||
this->selected--;
|
||||
if (this->scrollV > 0) {
|
||||
this->scrollV--;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
this->selected--;
|
||||
break;
|
||||
#endif
|
||||
case KEY_LEFT:
|
||||
case KEY_CTRLB:
|
||||
@ -384,71 +378,74 @@ bool Panel_onKey(Panel* this, int key) {
|
||||
this->scrollH -= CRT_scrollHAmount;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
case KEY_CTRLF:
|
||||
this->scrollH += CRT_scrollHAmount;
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
break;
|
||||
case KEY_PPAGE:
|
||||
this->selected -= (this->h - 1);
|
||||
this->scrollV -= (this->h - 1);
|
||||
if (this->selected < 0)
|
||||
this->selected = 0;
|
||||
if (this->scrollV < 0)
|
||||
this->scrollV = 0;
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
break;
|
||||
case KEY_NPAGE:
|
||||
this->selected += (this->h - 1);
|
||||
int size = Vector_size(this->items);
|
||||
if (this->selected < 0)
|
||||
this->selected = 0;
|
||||
if (this->selected >= size)
|
||||
this->selected = size - 1;
|
||||
this->scrollV += (this->h - 1);
|
||||
if (this->scrollV >= MAX(0, size - this->h))
|
||||
this->scrollV = MAX(0, size - this->h - 1);
|
||||
this->needsRedraw = true;
|
||||
return true;
|
||||
break;
|
||||
case KEY_HOME:
|
||||
this->selected = 0;
|
||||
return true;
|
||||
break;
|
||||
case KEY_END:
|
||||
this->selected = Vector_size(this->items) - 1;
|
||||
return true;
|
||||
this->selected = size - 1;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
// ensure selection within bounds
|
||||
if (this->selected < 0) {
|
||||
this->selected = 0;
|
||||
this->needsRedraw = true;
|
||||
} else if (this->selected >= size) {
|
||||
this->selected = size - 1;
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
|
||||
int size = Panel_size(this);
|
||||
if (!this->eventHandlerBuffer)
|
||||
this->eventHandlerBuffer = calloc(100, 1);
|
||||
if (!this->eventHandlerState)
|
||||
this->eventHandlerState = calloc(100, 1);
|
||||
char* buffer = this->eventHandlerState;
|
||||
|
||||
if (isalnum(ch)) {
|
||||
int len = strlen(this->eventHandlerBuffer);
|
||||
int len = strlen(buffer);
|
||||
if (len < 99) {
|
||||
this->eventHandlerBuffer[len] = ch;
|
||||
this->eventHandlerBuffer[len+1] = '\0';
|
||||
buffer[len] = ch;
|
||||
buffer[len+1] = '\0';
|
||||
}
|
||||
for (int try = 0; try < 2; try++) {
|
||||
len = strlen(this->eventHandlerBuffer);
|
||||
len = strlen(buffer);
|
||||
for (int i = 0; i < size; i++) {
|
||||
char* cur = ((ListItem*) Panel_get(this, i))->value;
|
||||
while (*cur == ' ') cur++;
|
||||
if (strncasecmp(cur, this->eventHandlerBuffer, len) == 0) {
|
||||
if (strncasecmp(cur, buffer, len) == 0) {
|
||||
Panel_setSelected(this, i);
|
||||
return HANDLED;
|
||||
}
|
||||
}
|
||||
this->eventHandlerBuffer[0] = ch;
|
||||
this->eventHandlerBuffer[1] = '\0';
|
||||
// if current word did not match,
|
||||
// retry considering the character the start of a new word.
|
||||
buffer[0] = ch;
|
||||
buffer[1] = '\0';
|
||||
}
|
||||
return HANDLED;
|
||||
} else if (ch != ERR) {
|
||||
this->eventHandlerBuffer[0] = '\0';
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
if (ch == 13) {
|
||||
return BREAK_LOOP;
|
||||
|
Reference in New Issue
Block a user