blob: ceb29f74c5c6ab6721ffd97244724ee8f9019915 [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;
Christian Göttsche19b51412020-11-23 16:23:18 +010058 Panel_draw(this->display, true, true);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020059 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);
Benny Baumann45869512020-11-01 01:09:51 +010067 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));
Benny Baumann45869512020-11-01 01:09:51 +010069 }
Hisham Muhammad466d4da2016-01-12 06:00:58 -020070}
71
72void InfoScreen_appendLine(InfoScreen* this, const char* line) {
Benny Baumann61e14d42020-10-31 23:28:02 +010073 ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020074 ListItem_append(last, line);
75 const char* incFilter = IncSet_filter(this->inc);
Benny Baumann45869512020-11-01 01:09:51 +010076 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 -020077 Panel_add(this->display, (Object*)last);
Benny Baumann45869512020-11-01 01:09:51 +010078 }
Hisham Muhammad466d4da2016-01-12 06:00:58 -020079}
80
81void InfoScreen_run(InfoScreen* this) {
82 Panel* panel = this->display;
83
Benny Baumann61e14d42020-10-31 23:28:02 +010084 if (As_InfoScreen(this)->scan)
85 InfoScreen_scan(this);
86
Hisham Muhammad466d4da2016-01-12 06:00:58 -020087 InfoScreen_draw(this);
88
89 bool looping = true;
90 while (looping) {
91
Christian Göttsche19b51412020-11-23 16:23:18 +010092 Panel_draw(panel, true, true);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020093
Hisham Muhammad8c653212018-02-18 10:38:49 -030094 if (this->inc->active) {
Benny Baumann61e14d42020-10-31 23:28:02 +010095 (void) move(LINES - 1, CRT_cursorX);
Hisham Muhammad8c653212018-02-18 10:38:49 -030096 }
Hisham645057d2016-05-19 16:09:47 -030097 set_escdelay(25);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020098 int ch = getch();
Daniel Flanagandd334442019-10-31 11:39:12 -050099
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200100 if (ch == ERR) {
101 if (As_InfoScreen(this)->onErr) {
102 InfoScreen_onErr(this);
103 continue;
104 }
105 }
106
107 if (ch == KEY_MOUSE) {
108 MEVENT mevent;
109 int ok = getmouse(&mevent);
Nathan Scott36ef4d42020-08-19 18:10:16 +1000110 if (ok == OK) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200111 if (mevent.y >= panel->y && mevent.y < LINES - 1) {
112 Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
113 ch = 0;
Nathan Scott9aa81682020-08-20 15:16:47 +1000114 } else if (mevent.y == LINES - 1) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200115 ch = IncSet_synthesizeEvent(this->inc, mevent.x);
Jorge Pereira8de04982020-06-11 13:41:13 -0300116 }
Christian Göttschef8208f22020-10-20 13:14:32 +0200117 }
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200118 }
119
120 if (this->inc->active) {
121 IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines);
122 continue;
123 }
Daniel Flanagandd334442019-10-31 11:39:12 -0500124
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200125 switch(ch) {
126 case ERR:
127 continue;
128 case KEY_F(3):
129 case '/':
130 IncSet_activate(this->inc, INC_SEARCH, panel);
131 break;
132 case KEY_F(4):
133 case '\\':
134 IncSet_activate(this->inc, INC_FILTER, panel);
135 break;
136 case KEY_F(5):
137 clear();
Benny Baumann45869512020-11-01 01:09:51 +0100138 if (As_InfoScreen(this)->scan)
139 InfoScreen_scan(this);
140
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200141 InfoScreen_draw(this);
142 break;
143 case '\014': // Ctrl+L
144 clear();
145 InfoScreen_draw(this);
146 break;
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200147 case 27:
Benny Baumannc49ca612020-11-21 16:59:38 +0100148 case 'q':
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200149 case KEY_F(10):
150 looping = false;
151 break;
152 case KEY_RESIZE:
Benny Baumann61e14d42020-10-31 23:28:02 +0100153 Panel_resize(panel, COLS, LINES - 2);
154 if (As_InfoScreen(this)->scan)
155 InfoScreen_scan(this);
Benny Baumann45869512020-11-01 01:09:51 +0100156
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200157 InfoScreen_draw(this);
158 break;
159 default:
160 if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) {
161 continue;
162 }
163 Panel_onKey(panel, ch);
164 }
165 }
166}