blob: 52117d0bf8a1cfb99a1e89cf748311399826c67f [file] [log] [blame]
Hisham Muhammad466d4da2016-01-12 06:00:58 -02001#include "InfoScreen.h"
2
3#include "config.h"
4#include "Object.h"
5#include "CRT.h"
6#include "IncSet.h"
7#include "ListItem.h"
8#include "Platform.h"
9#include "StringUtils.h"
10
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <stdarg.h>
15
Hisham Muhammad466d4da2016-01-12 06:00:58 -020016
Richardd5faf642017-07-22 21:41:19 -050017static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL};
Hisham Muhammad466d4da2016-01-12 06:00:58 -020018
Richardd5faf642017-07-22 21:41:19 -050019static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"};
Hisham Muhammad466d4da2016-01-12 06:00:58 -020020
21static int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
22
Christian Göttsche11f558f2020-08-20 21:58:14 +020023InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, const char* panelHeader) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -020024 this->process = process;
25 if (!bar) {
26 bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
27 }
28 this->display = Panel_new(0, 1, COLS, height, false, Class(ListItem), bar);
29 this->inc = IncSet_new(bar);
30 this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE);
31 Panel_setHeader(this->display, panelHeader);
32 return this;
33}
34
35InfoScreen* InfoScreen_done(InfoScreen* this) {
36 Panel_delete((Object*)this->display);
37 IncSet_delete(this->inc);
38 Vector_delete(this->lines);
39 return this;
40}
41
Christian Göttsche11f558f2020-08-20 21:58:14 +020042void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -020043 va_list ap;
44 va_start(ap, fmt);
ryenusff455b02020-10-03 00:12:31 +080045
46 char* title = xMalloc(COLS + 1);
47 int len = vsnprintf(title, COLS + 1, fmt, ap);
48 if (len > COLS) {
49 memset(&title[COLS - 3], '.', 3);
50 }
51
Hisham Muhammad466d4da2016-01-12 06:00:58 -020052 attrset(CRT_colors[METER_TEXT]);
53 mvhline(0, 0, ' ', COLS);
ryenusff455b02020-10-03 00:12:31 +080054 mvwprintw(stdscr, 0, 0, title);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020055 attrset(CRT_colors[DEFAULT_COLOR]);
Hisham7f9c82f2016-06-23 13:25:58 -030056 this->display->needsRedraw = true;
Hisham Muhammad466d4da2016-01-12 06:00:58 -020057 Panel_draw(this->display, true);
58 IncSet_drawBar(this->inc);
ryenusff455b02020-10-03 00:12:31 +080059 free(title);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020060 va_end(ap);
61}
62
63void InfoScreen_addLine(InfoScreen* this, const char* line) {
64 Vector_add(this->lines, (Object*) ListItem_new(line, 0));
65 const char* incFilter = IncSet_filter(this->inc);
66 if (!incFilter || String_contains_i(line, incFilter))
Christian Göttsche84394912020-09-28 12:17:52 +020067 Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines)-1));
Hisham Muhammad466d4da2016-01-12 06:00:58 -020068}
69
70void InfoScreen_appendLine(InfoScreen* this, const char* line) {
71 ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines)-1);
72 ListItem_append(last, line);
73 const char* incFilter = IncSet_filter(this->inc);
74 if (incFilter && Panel_get(this->display, Panel_size(this->display)-1) != (Object*)last && String_contains_i(line, incFilter))
75 Panel_add(this->display, (Object*)last);
76}
77
78void InfoScreen_run(InfoScreen* this) {
79 Panel* panel = this->display;
80
81 if (As_InfoScreen(this)->scan) InfoScreen_scan(this);
82 InfoScreen_draw(this);
83
84 bool looping = true;
85 while (looping) {
86
87 Panel_draw(panel, true);
88
Hisham Muhammad8c653212018-02-18 10:38:49 -030089 if (this->inc->active) {
90 (void) move(LINES-1, CRT_cursorX);
91 }
Hisham645057d2016-05-19 16:09:47 -030092 set_escdelay(25);
Hisham Muhammad466d4da2016-01-12 06:00:58 -020093 int ch = getch();
Daniel Flanagandd334442019-10-31 11:39:12 -050094
Hisham Muhammad466d4da2016-01-12 06:00:58 -020095 if (ch == ERR) {
96 if (As_InfoScreen(this)->onErr) {
97 InfoScreen_onErr(this);
98 continue;
99 }
100 }
101
102 if (ch == KEY_MOUSE) {
103 MEVENT mevent;
104 int ok = getmouse(&mevent);
Nathan Scott36ef4d42020-08-19 18:10:16 +1000105 if (ok == OK) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200106 if (mevent.y >= panel->y && mevent.y < LINES - 1) {
107 Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
108 ch = 0;
Nathan Scott9aa81682020-08-20 15:16:47 +1000109 } else if (mevent.y == LINES - 1) {
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200110 ch = IncSet_synthesizeEvent(this->inc, mevent.x);
Jorge Pereira8de04982020-06-11 13:41:13 -0300111 }
Nathan Scott36ef4d42020-08-19 18:10:16 +1000112 }
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200113 }
114
115 if (this->inc->active) {
116 IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines);
117 continue;
118 }
Daniel Flanagandd334442019-10-31 11:39:12 -0500119
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200120 switch(ch) {
121 case ERR:
122 continue;
123 case KEY_F(3):
124 case '/':
125 IncSet_activate(this->inc, INC_SEARCH, panel);
126 break;
127 case KEY_F(4):
128 case '\\':
129 IncSet_activate(this->inc, INC_FILTER, panel);
130 break;
131 case KEY_F(5):
132 clear();
133 if (As_InfoScreen(this)->scan) InfoScreen_scan(this);
134 InfoScreen_draw(this);
135 break;
136 case '\014': // Ctrl+L
137 clear();
138 InfoScreen_draw(this);
139 break;
140 case 'q':
141 case 27:
142 case KEY_F(10):
143 looping = false;
144 break;
145 case KEY_RESIZE:
146 Panel_resize(panel, COLS, LINES-2);
Christian Göttsche8efc8852020-09-29 10:25:20 +0200147 if (As_InfoScreen(this)->scan) InfoScreen_scan(this);
Hisham Muhammad466d4da2016-01-12 06:00:58 -0200148 InfoScreen_draw(this);
149 break;
150 default:
151 if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) {
152 continue;
153 }
154 Panel_onKey(panel, ch);
155 }
156 }
157}