blob: 102f0ba761ddcd29e7f91ea7f1c7fc9fad241a6e [file] [log] [blame]
Benny Baumann0f526292020-09-19 13:55:23 +02001#include "config.h" // IWYU pragma: keep
2
Hisham Muhammad466d4da2016-01-12 06:00:58 -02003#include "InfoScreen.h"
4
Benny Baumann0f526292020-09-19 13:55:23 +02005#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
Hisham Muhammad466d4da2016-01-12 06:00:58 -020010#include "CRT.h"
11#include "IncSet.h"
12#include "ListItem.h"
Benny Baumann0f526292020-09-19 13:55:23 +020013#include "Object.h"
14#include "ProvideCurses.h"
Benny Baumann872e5422020-10-14 20:21:09 +020015#include "XUtils.h"
Hisham Muhammad466d4da2016-01-12 06:00:58 -020016
Hisham Muhammad466d4da2016-01-12 06:00:58 -020017
Richardd5faf642017-07-22 21:41:19 -050018static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL};
Hisham Muhammad466d4da2016-01-12 06:00:58 -020019
Richardd5faf642017-07-22 21:41:19 -050020static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"};
Hisham Muhammad466d4da2016-01-12 06:00:58 -020021
22static int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
23
Christian Göttsche41eea8a2020-10-07 19:02:15 +020024InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -020025 this->process = process;
26 if (!bar) {
27 bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
28 }
29 this->display = Panel_new(0, 1, COLS, height, false, Class(ListItem), bar);
30 this->inc = IncSet_new(bar);
31 this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE);
32 Panel_setHeader(this->display, panelHeader);
33 return this;
34}
35
36InfoScreen* InfoScreen_done(InfoScreen* this) {
37 Panel_delete((Object*)this->display);
38 IncSet_delete(this->inc);
39 Vector_delete(this->lines);
40 return this;
41}
42
Christian Göttsche11f558f2020-08-20 21:58:14 +020043void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -020044 va_list ap;
45 va_start(ap, fmt);
ryenusff455b02020-10-03 00:12:31 +080046
47 char* title = xMalloc(COLS + 1);
48 int len = vsnprintf(title, COLS + 1, fmt, ap);
49 if (len > COLS) {
50 memset(&title[COLS - 3], '.', 3);
51 }
52
Hisham Muhammad466d4da2016-01-12 06:00:58 -020053 attrset(CRT_colors[METER_TEXT]);
54 mvhline(0, 0, ' ', COLS);
ryenusff455b02020-10-03 00:12:31 +080055 mvwprintw(stdscr, 0, 0, title);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020056 attrset(CRT_colors[DEFAULT_COLOR]);
Hisham7f9c82f2016-06-23 13:25:58 -030057 this->display->needsRedraw = true;
Hisham Muhammad466d4da2016-01-12 06:00:58 -020058 Panel_draw(this->display, true);
59 IncSet_drawBar(this->inc);
ryenusff455b02020-10-03 00:12:31 +080060 free(title);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020061 va_end(ap);
62}
63
64void InfoScreen_addLine(InfoScreen* this, const char* line) {
65 Vector_add(this->lines, (Object*) ListItem_new(line, 0));
66 const char* incFilter = IncSet_filter(this->inc);
67 if (!incFilter || String_contains_i(line, incFilter))
Benny Baumann61e14d42020-10-31 23:28:02 +010068 Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1));
Hisham Muhammad466d4da2016-01-12 06:00:58 -020069}
70
71void InfoScreen_appendLine(InfoScreen* this, const char* line) {
Benny Baumann61e14d42020-10-31 23:28:02 +010072 ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020073 ListItem_append(last, line);
74 const char* incFilter = IncSet_filter(this->inc);
Benny Baumann61e14d42020-10-31 23:28:02 +010075 if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter))
Hisham Muhammad466d4da2016-01-12 06:00:58 -020076 Panel_add(this->display, (Object*)last);
77}
78
79void InfoScreen_run(InfoScreen* this) {
80 Panel* panel = this->display;
81
Benny Baumann61e14d42020-10-31 23:28:02 +010082 if (As_InfoScreen(this)->scan)
83 InfoScreen_scan(this);
84
Hisham Muhammad466d4da2016-01-12 06:00:58 -020085 InfoScreen_draw(this);
86
87 bool looping = true;
88 while (looping) {
89
90 Panel_draw(panel, true);
91
Hisham Muhammad8c653212018-02-18 10:38:49 -030092 if (this->inc->active) {
Benny Baumann61e14d42020-10-31 23:28:02 +010093 (void) move(LINES - 1, CRT_cursorX);
Hisham Muhammad8c653212018-02-18 10:38:49 -030094 }
Hisham645057d2016-05-19 16:09:47 -030095 set_escdelay(25);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020096 int ch = getch();
Daniel Flanagandd334442019-10-31 11:39:12 -050097
Hisham Muhammad466d4da2016-01-12 06:00:58 -020098 if (ch == ERR) {
99 if (As_InfoScreen(this)->onErr) {
100 InfoScreen_onErr(this);
101 continue;
102 }
103 }
104
105 if (ch == KEY_MOUSE) {
106 MEVENT mevent;
107 int ok = getmouse(&mevent);
Nathan Scott36ef4d42020-08-19 18:10:16 +1000108 if (ok == OK) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200109 if (mevent.y >= panel->y && mevent.y < LINES - 1) {
110 Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
111 ch = 0;
Nathan Scott9aa81682020-08-20 15:16:47 +1000112 } else if (mevent.y == LINES - 1) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200113 ch = IncSet_synthesizeEvent(this->inc, mevent.x);
Jorge Pereira8de04982020-06-11 13:41:13 -0300114 }
Christian Göttschef8208f22020-10-20 13:14:32 +0200115 }
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200116 }
117
118 if (this->inc->active) {
119 IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines);
120 continue;
121 }
Daniel Flanagandd334442019-10-31 11:39:12 -0500122
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200123 switch(ch) {
124 case ERR:
125 continue;
126 case KEY_F(3):
127 case '/':
128 IncSet_activate(this->inc, INC_SEARCH, panel);
129 break;
130 case KEY_F(4):
131 case '\\':
132 IncSet_activate(this->inc, INC_FILTER, panel);
133 break;
134 case KEY_F(5):
135 clear();
136 if (As_InfoScreen(this)->scan) InfoScreen_scan(this);
137 InfoScreen_draw(this);
138 break;
139 case '\014': // Ctrl+L
140 clear();
141 InfoScreen_draw(this);
142 break;
143 case 'q':
144 case 27:
145 case KEY_F(10):
146 looping = false;
147 break;
148 case KEY_RESIZE:
Benny Baumann61e14d42020-10-31 23:28:02 +0100149 Panel_resize(panel, COLS, LINES - 2);
150 if (As_InfoScreen(this)->scan)
151 InfoScreen_scan(this);
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200152 InfoScreen_draw(this);
153 break;
154 default:
155 if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) {
156 continue;
157 }
158 Panel_onKey(panel, ch);
159 }
160 }
161}