blob: 83874b0e266c5ca57c73e85b4ba4b229f77b446d [file] [log] [blame]
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -03001#include "../util.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -03002#include "../string2.h"
Taeung Song41840d22016-06-23 17:55:17 +09003#include "../config.h"
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -03004#include "../../perf.h"
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -03005#include "libslang.h"
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -02006#include "ui.h"
Arnaldo Carvalho de Melo71172ed2011-10-25 13:45:16 -02007#include "util.h"
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -03008#include <linux/compiler.h>
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -03009#include <linux/list.h>
10#include <linux/rbtree.h>
11#include <stdlib.h>
12#include <sys/ttydefaults.h>
13#include "browser.h"
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -030014#include "helpline.h"
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -020015#include "keysyms.h"
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -030016#include "../color.h"
Arnaldo Carvalho de Melo3d689ed2017-04-17 16:10:49 -030017#include "sane_ctype.h"
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -030018
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -020019static int ui_browser__percent_color(struct ui_browser *browser,
20 double percent, bool current)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -030021{
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -020022 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -030023 return HE_COLORSET_SELECTED;
24 if (percent >= MIN_RED)
25 return HE_COLORSET_TOP;
26 if (percent >= MIN_GREEN)
27 return HE_COLORSET_MEDIUM;
28 return HE_COLORSET_NORMAL;
29}
30
Arnaldo Carvalho de Melo08709162012-04-02 12:48:56 -030031int ui_browser__set_color(struct ui_browser *browser, int color)
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030032{
Arnaldo Carvalho de Melo08709162012-04-02 12:48:56 -030033 int ret = browser->current_color;
34 browser->current_color = color;
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030035 SLsmg_set_color(color);
Arnaldo Carvalho de Melo08709162012-04-02 12:48:56 -030036 return ret;
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030037}
38
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030039void ui_browser__set_percent_color(struct ui_browser *browser,
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030040 double percent, bool current)
41{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030042 int color = ui_browser__percent_color(browser, percent, current);
43 ui_browser__set_color(browser, color);
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030044}
45
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030046void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030047{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030048 SLsmg_gotorc(browser->y + y, browser->x + x);
Arnaldo Carvalho de Melo8f9bbc42010-08-11 14:51:47 -030049}
50
Arnaldo Carvalho de Melo26270a02015-08-11 12:24:27 -030051void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg,
52 unsigned int width)
53{
54 slsmg_write_nstring(msg, width);
55}
56
Arnaldo Carvalho de Melo517dfdb2015-08-11 12:50:55 -030057void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...)
58{
59 va_list args;
60
61 va_start(args, fmt);
62 slsmg_vprintf(fmt, args);
63 va_end(args);
64}
65
Arnaldo Carvalho de Melo250611c2011-10-14 12:27:54 -030066static struct list_head *
67ui_browser__list_head_filter_entries(struct ui_browser *browser,
68 struct list_head *pos)
69{
70 do {
71 if (!browser->filter || !browser->filter(browser, pos))
72 return pos;
73 pos = pos->next;
74 } while (pos != browser->entries);
75
76 return NULL;
77}
78
79static struct list_head *
80ui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
81 struct list_head *pos)
82{
83 do {
84 if (!browser->filter || !browser->filter(browser, pos))
85 return pos;
86 pos = pos->prev;
87 } while (pos != browser->entries);
88
89 return NULL;
90}
91
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030092void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -030093{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030094 struct list_head *head = browser->entries;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -030095 struct list_head *pos;
96
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -030097 if (browser->nr_entries == 0)
Arnaldo Carvalho de Melo250611c2011-10-14 12:27:54 -030098 return;
99
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300100 switch (whence) {
101 case SEEK_SET:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300102 pos = ui_browser__list_head_filter_entries(browser, head->next);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300103 break;
104 case SEEK_CUR:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300105 pos = browser->top;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300106 break;
107 case SEEK_END:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300108 pos = ui_browser__list_head_filter_prev_entries(browser, head->prev);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300109 break;
110 default:
111 return;
112 }
113
Arnaldo Carvalho de Melo250611c2011-10-14 12:27:54 -0300114 assert(pos != NULL);
115
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300116 if (offset > 0) {
117 while (offset-- != 0)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300118 pos = ui_browser__list_head_filter_entries(browser, pos->next);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300119 } else {
120 while (offset++ != 0)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300121 pos = ui_browser__list_head_filter_prev_entries(browser, pos->prev);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300122 }
123
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300124 browser->top = pos;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300125}
126
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300127void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300128{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300129 struct rb_root *root = browser->entries;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300130 struct rb_node *nd;
131
132 switch (whence) {
133 case SEEK_SET:
134 nd = rb_first(root);
135 break;
136 case SEEK_CUR:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300137 nd = browser->top;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300138 break;
139 case SEEK_END:
140 nd = rb_last(root);
141 break;
142 default:
143 return;
144 }
145
146 if (offset > 0) {
147 while (offset-- != 0)
148 nd = rb_next(nd);
149 } else {
150 while (offset++ != 0)
151 nd = rb_prev(nd);
152 }
153
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300154 browser->top = nd;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300155}
156
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300157unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300158{
159 struct rb_node *nd;
160 int row = 0;
161
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300162 if (browser->top == NULL)
163 browser->top = rb_first(browser->entries);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300164
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300165 nd = browser->top;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300166
167 while (nd != NULL) {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300168 ui_browser__gotorc(browser, row, 0);
169 browser->write(browser, nd, row);
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300170 if (++row == browser->rows)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300171 break;
172 nd = rb_next(nd);
173 }
174
175 return row;
176}
177
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300178bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300179{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300180 return browser->top_idx + row == browser->index;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300181}
182
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300183void ui_browser__refresh_dimensions(struct ui_browser *browser)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300184{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300185 browser->width = SLtt_Screen_Cols - 1;
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300186 browser->height = browser->rows = SLtt_Screen_Rows - 2;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300187 browser->y = 1;
188 browser->x = 0;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300189}
190
Arnaldo Carvalho de Melo4610e412011-10-26 12:04:37 -0200191void ui_browser__handle_resize(struct ui_browser *browser)
192{
193 ui__refresh_dimensions(false);
194 ui_browser__show(browser, browser->title, ui_helpline__current);
195 ui_browser__refresh(browser);
196}
197
Arnaldo Carvalho de Melo7b275092011-10-29 12:15:04 -0200198int ui_browser__warning(struct ui_browser *browser, int timeout,
199 const char *format, ...)
Arnaldo Carvalho de Melo4610e412011-10-26 12:04:37 -0200200{
201 va_list args;
Arnaldo Carvalho de Melo7b275092011-10-29 12:15:04 -0200202 char *text;
203 int key = 0, err;
Arnaldo Carvalho de Melo4610e412011-10-26 12:04:37 -0200204
205 va_start(args, format);
Arnaldo Carvalho de Melo7b275092011-10-29 12:15:04 -0200206 err = vasprintf(&text, format, args);
Arnaldo Carvalho de Melo4610e412011-10-26 12:04:37 -0200207 va_end(args);
208
Arnaldo Carvalho de Melo7b275092011-10-29 12:15:04 -0200209 if (err < 0) {
210 va_start(args, format);
211 ui_helpline__vpush(format, args);
212 va_end(args);
213 } else {
zhangdianfang7f3e5082014-05-30 08:53:58 +0800214 while ((key = ui__question_window("Warning!", text,
Arnaldo Carvalho de Melo7b275092011-10-29 12:15:04 -0200215 "Press any key...",
216 timeout)) == K_RESIZE)
217 ui_browser__handle_resize(browser);
218 free(text);
219 }
220
Arnaldo Carvalho de Melo4610e412011-10-26 12:04:37 -0200221 return key;
222}
223
224int ui_browser__help_window(struct ui_browser *browser, const char *text)
225{
226 int key;
227
228 while ((key = ui__help_window(text)) == K_RESIZE)
229 ui_browser__handle_resize(browser);
230
231 return key;
232}
233
234bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text)
235{
236 int key;
237
238 while ((key = ui__dialog_yesno(text)) == K_RESIZE)
239 ui_browser__handle_resize(browser);
240
241 return key == K_ENTER || toupper(key) == 'Y';
242}
243
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300244void ui_browser__reset_index(struct ui_browser *browser)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300245{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300246 browser->index = browser->top_idx = 0;
247 browser->seek(browser, 0, SEEK_SET);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300248}
249
Arnaldo Carvalho de Melob210b3b2011-02-25 11:33:31 -0300250void __ui_browser__show_title(struct ui_browser *browser, const char *title)
251{
252 SLsmg_gotorc(0, 0);
Arnaldo Carvalho de Melo6692c262013-03-28 11:34:10 -0300253 ui_browser__set_color(browser, HE_COLORSET_ROOT);
Arnaldo Carvalho de Melo26270a02015-08-11 12:24:27 -0300254 ui_browser__write_nstring(browser, title, browser->width + 1);
Arnaldo Carvalho de Melob210b3b2011-02-25 11:33:31 -0300255}
256
257void ui_browser__show_title(struct ui_browser *browser, const char *title)
258{
259 pthread_mutex_lock(&ui__lock);
260 __ui_browser__show_title(browser, title);
261 pthread_mutex_unlock(&ui__lock);
262}
263
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300264int ui_browser__show(struct ui_browser *browser, const char *title,
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300265 const char *helpline, ...)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300266{
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300267 int err;
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300268 va_list ap;
269
Arnaldo Carvalho de Melofa70b5d2014-07-01 16:34:42 -0300270 if (browser->refresh_dimensions == NULL)
271 browser->refresh_dimensions = ui_browser__refresh_dimensions;
272
273 browser->refresh_dimensions(browser);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300274
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200275 pthread_mutex_lock(&ui__lock);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300276 __ui_browser__show_title(browser, title);
Arnaldo Carvalho de Melo469917c2010-09-13 10:25:04 -0300277
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300278 browser->title = title;
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300279 zfree(&browser->helpline);
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300280
281 va_start(ap, helpline);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300282 err = vasprintf(&browser->helpline, helpline, ap);
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300283 va_end(ap);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300284 if (err > 0)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300285 ui_helpline__push(browser->helpline);
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200286 pthread_mutex_unlock(&ui__lock);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300287 return err ? 0 : -1;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300288}
289
Arnaldo Carvalho de Melo3184c472013-12-19 16:25:17 -0300290void ui_browser__hide(struct ui_browser *browser)
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300291{
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200292 pthread_mutex_lock(&ui__lock);
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300293 ui_helpline__pop();
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300294 zfree(&browser->helpline);
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200295 pthread_mutex_unlock(&ui__lock);
Arnaldo Carvalho de Melo59e8fe32010-08-10 15:44:20 -0300296}
297
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300298static void ui_browser__scrollbar_set(struct ui_browser *browser)
299{
300 int height = browser->height, h = 0, pct = 0,
301 col = browser->width,
Jiri Olsa89632972014-06-19 13:41:14 +0200302 row = 0;
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300303
304 if (browser->nr_entries > 1) {
305 pct = ((browser->index * (browser->height - 1)) /
306 (browser->nr_entries - 1));
307 }
308
Arnaldo Carvalho de Melo04581222011-10-26 08:19:05 -0200309 SLsmg_set_char_set(1);
310
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300311 while (h < height) {
312 ui_browser__gotorc(browser, row++, col);
Arnaldo Carvalho de Melo04581222011-10-26 08:19:05 -0200313 SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_CKBRD_CHAR);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300314 ++h;
315 }
Arnaldo Carvalho de Melo04581222011-10-26 08:19:05 -0200316
317 SLsmg_set_char_set(0);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300318}
319
320static int __ui_browser__refresh(struct ui_browser *browser)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300321{
322 int row;
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200323 int width = browser->width;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300324
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300325 row = browser->refresh(browser);
326 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200327
328 if (!browser->use_navkeypressed || browser->navkeypressed)
329 ui_browser__scrollbar_set(browser);
330 else
331 width += 1;
332
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300333 SLsmg_fill_region(browser->y + row, browser->x,
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200334 browser->height - row, width, ' ');
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300335
336 return 0;
337}
338
339int ui_browser__refresh(struct ui_browser *browser)
340{
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200341 pthread_mutex_lock(&ui__lock);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300342 __ui_browser__refresh(browser);
Arnaldo Carvalho de Melo5c35d692011-02-09 11:38:43 -0200343 pthread_mutex_unlock(&ui__lock);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300344
345 return 0;
346}
347
Arnaldo Carvalho de Melo900e14a2011-10-11 16:15:39 -0300348/*
349 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
350 * forget about any reference to any entry in the underlying data structure,
351 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
352 * after an output_resort and hist decay.
353 */
354void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
355{
356 off_t offset = nr_entries - browser->nr_entries;
357
358 browser->nr_entries = nr_entries;
359
360 if (offset < 0) {
361 if (browser->top_idx < (u64)-offset)
362 offset = -browser->top_idx;
363
364 browser->index += offset;
365 browser->top_idx += offset;
366 }
367
Arnaldo Carvalho de Melo437cfe72011-10-14 09:31:53 -0300368 browser->top = NULL;
Arnaldo Carvalho de Melo900e14a2011-10-11 16:15:39 -0300369 browser->seek(browser, browser->top_idx, SEEK_SET);
370}
371
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300372int ui_browser__run(struct ui_browser *browser, int delay_secs)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300373{
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300374 int err, key;
Arnaldo Carvalho de Melob50e0032010-08-11 10:07:43 -0300375
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300376 while (1) {
377 off_t offset;
378
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300379 pthread_mutex_lock(&ui__lock);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300380 err = __ui_browser__refresh(browser);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300381 SLsmg_refresh();
382 pthread_mutex_unlock(&ui__lock);
383 if (err < 0)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300384 break;
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300385
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200386 key = ui__getch(delay_secs);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300387
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200388 if (key == K_RESIZE) {
Arnaldo Carvalho de Melo71172ed2011-10-25 13:45:16 -0200389 ui__refresh_dimensions(false);
Arnaldo Carvalho de Melofa70b5d2014-07-01 16:34:42 -0300390 browser->refresh_dimensions(browser);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300391 __ui_browser__show_title(browser, browser->title);
392 ui_helpline__puts(browser->helpline);
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300393 continue;
394 }
395
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300396 if (browser->use_navkeypressed && !browser->navkeypressed) {
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200397 if (key == K_DOWN || key == K_UP ||
Arnaldo Carvalho de Melofaae6f62015-08-11 17:14:40 -0300398 (browser->columns && (key == K_LEFT || key == K_RIGHT)) ||
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200399 key == K_PGDN || key == K_PGUP ||
400 key == K_HOME || key == K_END ||
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200401 key == ' ') {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300402 browser->navkeypressed = true;
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200403 continue;
404 } else
405 return key;
406 }
407
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300408 switch (key) {
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200409 case K_DOWN:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300410 if (browser->index == browser->nr_entries - 1)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300411 break;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300412 ++browser->index;
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300413 if (browser->index == browser->top_idx + browser->rows) {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300414 ++browser->top_idx;
415 browser->seek(browser, +1, SEEK_CUR);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300416 }
417 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200418 case K_UP:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300419 if (browser->index == 0)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300420 break;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300421 --browser->index;
422 if (browser->index < browser->top_idx) {
423 --browser->top_idx;
424 browser->seek(browser, -1, SEEK_CUR);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300425 }
426 break;
Arnaldo Carvalho de Melofaae6f62015-08-11 17:14:40 -0300427 case K_RIGHT:
428 if (!browser->columns)
429 goto out;
430 if (browser->horiz_scroll < browser->columns - 1)
431 ++browser->horiz_scroll;
432 break;
433 case K_LEFT:
434 if (!browser->columns)
435 goto out;
436 if (browser->horiz_scroll != 0)
437 --browser->horiz_scroll;
438 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200439 case K_PGDN:
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300440 case ' ':
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300441 if (browser->top_idx + browser->rows > browser->nr_entries - 1)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300442 break;
443
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300444 offset = browser->rows;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300445 if (browser->index + offset > browser->nr_entries - 1)
446 offset = browser->nr_entries - 1 - browser->index;
447 browser->index += offset;
448 browser->top_idx += offset;
449 browser->seek(browser, +offset, SEEK_CUR);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300450 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200451 case K_PGUP:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300452 if (browser->top_idx == 0)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300453 break;
454
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300455 if (browser->top_idx < browser->rows)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300456 offset = browser->top_idx;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300457 else
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300458 offset = browser->rows;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300459
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300460 browser->index -= offset;
461 browser->top_idx -= offset;
462 browser->seek(browser, -offset, SEEK_CUR);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300463 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200464 case K_HOME:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300465 ui_browser__reset_index(browser);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300466 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200467 case K_END:
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300468 offset = browser->rows - 1;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300469 if (offset >= browser->nr_entries)
470 offset = browser->nr_entries - 1;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300471
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300472 browser->index = browser->nr_entries - 1;
473 browser->top_idx = browser->index - offset;
474 browser->seek(browser, -offset, SEEK_END);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300475 break;
476 default:
Arnaldo Carvalho de Melofaae6f62015-08-11 17:14:40 -0300477 out:
Arnaldo Carvalho de Melo3af6e332011-10-13 08:52:46 -0300478 return key;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300479 }
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300480 }
Arnaldo Carvalho de Melob50e0032010-08-11 10:07:43 -0300481 return -1;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300482}
483
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300484unsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300485{
486 struct list_head *pos;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300487 struct list_head *head = browser->entries;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300488 int row = 0;
489
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300490 if (browser->top == NULL || browser->top == browser->entries)
491 browser->top = ui_browser__list_head_filter_entries(browser, head->next);
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300492
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300493 pos = browser->top;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300494
495 list_for_each_from(pos, head) {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300496 if (!browser->filter || !browser->filter(browser, pos)) {
497 ui_browser__gotorc(browser, row, 0);
498 browser->write(browser, pos, row);
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300499 if (++row == browser->rows)
Arnaldo Carvalho de Melo250611c2011-10-14 12:27:54 -0300500 break;
501 }
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300502 }
503
504 return row;
505}
506
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -0300507static struct ui_browser_colorset {
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200508 const char *name, *fg, *bg;
509 int colorset;
510} ui_browser__colorsets[] = {
511 {
512 .colorset = HE_COLORSET_TOP,
513 .name = "top",
514 .fg = "red",
Arnaldo Carvalho de Melo82e0af82011-10-19 00:30:32 -0200515 .bg = "default",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200516 },
517 {
518 .colorset = HE_COLORSET_MEDIUM,
519 .name = "medium",
520 .fg = "green",
Arnaldo Carvalho de Melo82e0af82011-10-19 00:30:32 -0200521 .bg = "default",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200522 },
523 {
524 .colorset = HE_COLORSET_NORMAL,
525 .name = "normal",
Arnaldo Carvalho de Melo82e0af82011-10-19 00:30:32 -0200526 .fg = "default",
527 .bg = "default",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200528 },
529 {
530 .colorset = HE_COLORSET_SELECTED,
531 .name = "selected",
532 .fg = "black",
Ingo Molnar8d7d3772015-03-05 11:32:13 +0100533 .bg = "yellow",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200534 },
535 {
Taeung Song78ce08d2016-01-08 17:16:11 +0900536 .colorset = HE_COLORSET_JUMP_ARROWS,
537 .name = "jump_arrows",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200538 .fg = "blue",
Arnaldo Carvalho de Melo82e0af82011-10-19 00:30:32 -0200539 .bg = "default",
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200540 },
541 {
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -0300542 .colorset = HE_COLORSET_ADDR,
543 .name = "addr",
544 .fg = "magenta",
545 .bg = "default",
546 },
547 {
Arnaldo Carvalho de Melo6692c262013-03-28 11:34:10 -0300548 .colorset = HE_COLORSET_ROOT,
549 .name = "root",
550 .fg = "white",
551 .bg = "blue",
552 },
553 {
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200554 .name = NULL,
555 }
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300556};
557
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200558
559static int ui_browser__color_config(const char *var, const char *value,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300560 void *data __maybe_unused)
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200561{
562 char *fg = NULL, *bg;
563 int i;
564
565 /* same dir for all commands */
566 if (prefixcmp(var, "colors.") != 0)
567 return 0;
568
569 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
570 const char *name = var + 7;
571
572 if (strcmp(ui_browser__colorsets[i].name, name) != 0)
573 continue;
574
575 fg = strdup(value);
576 if (fg == NULL)
577 break;
578
579 bg = strchr(fg, ',');
580 if (bg == NULL)
581 break;
582
583 *bg = '\0';
Taeung Songe21600f2017-04-07 23:24:19 +0900584 bg = ltrim(++bg);
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200585 ui_browser__colorsets[i].bg = bg;
586 ui_browser__colorsets[i].fg = fg;
587 return 0;
588 }
589
590 free(fg);
591 return -1;
592}
593
Arnaldo Carvalho de Melo1056d3d2011-10-26 07:11:03 -0200594void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence)
595{
596 switch (whence) {
597 case SEEK_SET:
598 browser->top = browser->entries;
599 break;
600 case SEEK_CUR:
601 browser->top = browser->top + browser->top_idx + offset;
602 break;
603 case SEEK_END:
Arnaldo Carvalho de Melo48d038f2013-11-14 15:30:41 -0300604 browser->top = browser->top + browser->nr_entries - 1 + offset;
Arnaldo Carvalho de Melo1056d3d2011-10-26 07:11:03 -0200605 break;
606 default:
607 return;
608 }
609}
610
611unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
612{
613 unsigned int row = 0, idx = browser->top_idx;
614 char **pos;
615
616 if (browser->top == NULL)
617 browser->top = browser->entries;
618
619 pos = (char **)browser->top;
620 while (idx < browser->nr_entries) {
621 if (!browser->filter || !browser->filter(browser, *pos)) {
622 ui_browser__gotorc(browser, row, 0);
623 browser->write(browser, pos, row);
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300624 if (++row == browser->rows)
Arnaldo Carvalho de Melo1056d3d2011-10-26 07:11:03 -0200625 break;
626 }
627
628 ++idx;
629 ++pos;
630 }
631
632 return row;
633}
634
Arnaldo Carvalho de Melo4656cca2012-05-03 13:07:05 -0300635void __ui_browser__vline(struct ui_browser *browser, unsigned int column,
636 u16 start, u16 end)
637{
638 SLsmg_set_char_set(1);
639 ui_browser__gotorc(browser, start, column);
640 SLsmg_draw_vline(end - start + 1);
641 SLsmg_set_char_set(0);
642}
643
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300644void ui_browser__write_graph(struct ui_browser *browser __maybe_unused,
645 int graph)
Arnaldo Carvalho de Melo59d038d2012-04-20 16:26:14 -0300646{
647 SLsmg_set_char_set(1);
648 SLsmg_write_char(graph);
649 SLsmg_set_char_set(0);
650}
651
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300652static void __ui_browser__line_arrow_up(struct ui_browser *browser,
653 unsigned int column,
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300654 u64 start, u64 end)
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300655{
656 unsigned int row, end_row;
657
658 SLsmg_set_char_set(1);
659
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300660 if (start < browser->top_idx + browser->rows) {
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300661 row = start - browser->top_idx;
662 ui_browser__gotorc(browser, row, column);
663 SLsmg_write_char(SLSMG_LLCORN_CHAR);
664 ui_browser__gotorc(browser, row, column + 1);
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300665 SLsmg_draw_hline(2);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300666
667 if (row-- == 0)
668 goto out;
669 } else
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300670 row = browser->rows - 1;
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300671
672 if (end > browser->top_idx)
673 end_row = end - browser->top_idx;
674 else
675 end_row = 0;
676
677 ui_browser__gotorc(browser, end_row, column);
678 SLsmg_draw_vline(row - end_row + 1);
679
680 ui_browser__gotorc(browser, end_row, column);
681 if (end >= browser->top_idx) {
682 SLsmg_write_char(SLSMG_ULCORN_CHAR);
683 ui_browser__gotorc(browser, end_row, column + 1);
684 SLsmg_write_char(SLSMG_HLINE_CHAR);
685 ui_browser__gotorc(browser, end_row, column + 2);
686 SLsmg_write_char(SLSMG_RARROW_CHAR);
687 }
688out:
689 SLsmg_set_char_set(0);
690}
691
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300692static void __ui_browser__line_arrow_down(struct ui_browser *browser,
693 unsigned int column,
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300694 u64 start, u64 end)
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300695{
696 unsigned int row, end_row;
697
698 SLsmg_set_char_set(1);
699
700 if (start >= browser->top_idx) {
701 row = start - browser->top_idx;
702 ui_browser__gotorc(browser, row, column);
703 SLsmg_write_char(SLSMG_ULCORN_CHAR);
704 ui_browser__gotorc(browser, row, column + 1);
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300705 SLsmg_draw_hline(2);
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300706
Jin Yao80f62582017-06-08 14:01:44 +0800707 if (++row == 0)
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300708 goto out;
709 } else
710 row = 0;
711
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300712 if (end >= browser->top_idx + browser->rows)
713 end_row = browser->rows - 1;
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300714 else
Davidlohr Buesob2222132013-11-12 22:24:24 -0800715 end_row = end - browser->top_idx;
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300716
717 ui_browser__gotorc(browser, row, column);
718 SLsmg_draw_vline(end_row - row + 1);
719
720 ui_browser__gotorc(browser, end_row, column);
Arnaldo Carvalho de Melo62c95ae2014-07-01 11:07:54 -0300721 if (end < browser->top_idx + browser->rows) {
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300722 SLsmg_write_char(SLSMG_LLCORN_CHAR);
723 ui_browser__gotorc(browser, end_row, column + 1);
724 SLsmg_write_char(SLSMG_HLINE_CHAR);
725 ui_browser__gotorc(browser, end_row, column + 2);
726 SLsmg_write_char(SLSMG_RARROW_CHAR);
727 }
728out:
729 SLsmg_set_char_set(0);
730}
731
732void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300733 u64 start, u64 end)
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300734{
735 if (start > end)
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300736 __ui_browser__line_arrow_up(browser, column, start, end);
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300737 else
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300738 __ui_browser__line_arrow_down(browser, column, start, end);
Arnaldo Carvalho de Melo944e1ab2012-04-27 16:27:52 -0300739}
740
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300741void ui_browser__init(void)
742{
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200743 int i = 0;
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300744
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200745 perf_config(ui_browser__color_config, NULL);
746
747 while (ui_browser__colorsets[i].name) {
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -0300748 struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
Arnaldo Carvalho de Meloe039fc72011-10-18 15:50:51 -0200749 sltt_set_color(c->colorset, c->name, c->fg, c->bg);
750 }
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -0300751
752 annotate_browser__init();
Arnaldo Carvalho de Meloef8f34a2010-08-06 17:35:02 -0300753}