3 #include "../../perf.h"
8 #include <linux/compiler.h>
9 #include <linux/list.h>
10 #include <linux/rbtree.h>
12 #include <sys/ttydefaults.h>
18 static int ui_browser__percent_color(struct ui_browser
*browser
,
19 double percent
, bool current
)
21 if (current
&& (!browser
->use_navkeypressed
|| browser
->navkeypressed
))
22 return HE_COLORSET_SELECTED
;
23 if (percent
>= MIN_RED
)
24 return HE_COLORSET_TOP
;
25 if (percent
>= MIN_GREEN
)
26 return HE_COLORSET_MEDIUM
;
27 return HE_COLORSET_NORMAL
;
30 void ui_browser__set_color(struct ui_browser
*self __used
, int color
)
32 SLsmg_set_color(color
);
35 void ui_browser__set_percent_color(struct ui_browser
*self
,
36 double percent
, bool current
)
38 int color
= ui_browser__percent_color(self
, percent
, current
);
39 ui_browser__set_color(self
, color
);
42 void ui_browser__gotorc(struct ui_browser
*self
, int y
, int x
)
44 SLsmg_gotorc(self
->y
+ y
, self
->x
+ x
);
47 static struct list_head
*
48 ui_browser__list_head_filter_entries(struct ui_browser
*browser
,
49 struct list_head
*pos
)
52 if (!browser
->filter
|| !browser
->filter(browser
, pos
))
55 } while (pos
!= browser
->entries
);
60 static struct list_head
*
61 ui_browser__list_head_filter_prev_entries(struct ui_browser
*browser
,
62 struct list_head
*pos
)
65 if (!browser
->filter
|| !browser
->filter(browser
, pos
))
68 } while (pos
!= browser
->entries
);
73 void ui_browser__list_head_seek(struct ui_browser
*self
, off_t offset
, int whence
)
75 struct list_head
*head
= self
->entries
;
76 struct list_head
*pos
;
78 if (self
->nr_entries
== 0)
83 pos
= ui_browser__list_head_filter_entries(self
, head
->next
);
89 pos
= ui_browser__list_head_filter_prev_entries(self
, head
->prev
);
99 pos
= ui_browser__list_head_filter_entries(self
, pos
->next
);
101 while (offset
++ != 0)
102 pos
= ui_browser__list_head_filter_prev_entries(self
, pos
->prev
);
108 void ui_browser__rb_tree_seek(struct ui_browser
*self
, off_t offset
, int whence
)
110 struct rb_root
*root
= self
->entries
;
128 while (offset
-- != 0)
131 while (offset
++ != 0)
138 unsigned int ui_browser__rb_tree_refresh(struct ui_browser
*self
)
143 if (self
->top
== NULL
)
144 self
->top
= rb_first(self
->entries
);
149 ui_browser__gotorc(self
, row
, 0);
150 self
->write(self
, nd
, row
);
151 if (++row
== self
->height
)
159 bool ui_browser__is_current_entry(struct ui_browser
*self
, unsigned row
)
161 return self
->top_idx
+ row
== self
->index
;
164 void ui_browser__refresh_dimensions(struct ui_browser
*self
)
166 self
->width
= SLtt_Screen_Cols
- 1;
167 self
->height
= SLtt_Screen_Rows
- 2;
172 void ui_browser__reset_index(struct ui_browser
*self
)
174 self
->index
= self
->top_idx
= 0;
175 self
->seek(self
, 0, SEEK_SET
);
178 void __ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
181 ui_browser__set_color(browser
, NEWT_COLORSET_ROOT
);
182 slsmg_write_nstring(title
, browser
->width
+ 1);
185 void ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
187 pthread_mutex_lock(&ui__lock
);
188 __ui_browser__show_title(browser
, title
);
189 pthread_mutex_unlock(&ui__lock
);
192 int ui_browser__show(struct ui_browser
*self
, const char *title
,
193 const char *helpline
, ...)
198 ui_browser__refresh_dimensions(self
);
200 pthread_mutex_lock(&ui__lock
);
201 __ui_browser__show_title(self
, title
);
204 free(self
->helpline
);
205 self
->helpline
= NULL
;
207 va_start(ap
, helpline
);
208 err
= vasprintf(&self
->helpline
, helpline
, ap
);
211 ui_helpline__push(self
->helpline
);
212 pthread_mutex_unlock(&ui__lock
);
216 void ui_browser__hide(struct ui_browser
*browser __used
)
218 pthread_mutex_lock(&ui__lock
);
220 pthread_mutex_unlock(&ui__lock
);
223 static void ui_browser__scrollbar_set(struct ui_browser
*browser
)
225 int height
= browser
->height
, h
= 0, pct
= 0,
226 col
= browser
->width
,
227 row
= browser
->y
- 1;
229 if (browser
->nr_entries
> 1) {
230 pct
= ((browser
->index
* (browser
->height
- 1)) /
231 (browser
->nr_entries
- 1));
235 ui_browser__gotorc(browser
, row
++, col
);
236 SLsmg_set_char_set(1);
237 SLsmg_write_char(h
== pct
? SLSMG_DIAMOND_CHAR
: SLSMG_BOARD_CHAR
);
238 SLsmg_set_char_set(0);
243 static int __ui_browser__refresh(struct ui_browser
*browser
)
246 int width
= browser
->width
;
248 row
= browser
->refresh(browser
);
249 ui_browser__set_color(browser
, HE_COLORSET_NORMAL
);
251 if (!browser
->use_navkeypressed
|| browser
->navkeypressed
)
252 ui_browser__scrollbar_set(browser
);
256 SLsmg_fill_region(browser
->y
+ row
, browser
->x
,
257 browser
->height
- row
, width
, ' ');
262 int ui_browser__refresh(struct ui_browser
*browser
)
264 pthread_mutex_lock(&ui__lock
);
265 __ui_browser__refresh(browser
);
266 pthread_mutex_unlock(&ui__lock
);
272 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
273 * forget about any reference to any entry in the underlying data structure,
274 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
275 * after an output_resort and hist decay.
277 void ui_browser__update_nr_entries(struct ui_browser
*browser
, u32 nr_entries
)
279 off_t offset
= nr_entries
- browser
->nr_entries
;
281 browser
->nr_entries
= nr_entries
;
284 if (browser
->top_idx
< (u64
)-offset
)
285 offset
= -browser
->top_idx
;
287 browser
->index
+= offset
;
288 browser
->top_idx
+= offset
;
292 browser
->seek(browser
, browser
->top_idx
, SEEK_SET
);
295 int ui_browser__run(struct ui_browser
*self
, int delay_secs
)
302 pthread_mutex_lock(&ui__lock
);
303 err
= __ui_browser__refresh(self
);
305 pthread_mutex_unlock(&ui__lock
);
309 key
= ui__getch(delay_secs
);
311 if (key
== K_RESIZE
) {
312 ui__refresh_dimensions(false);
313 ui_browser__refresh_dimensions(self
);
314 __ui_browser__show_title(self
, self
->title
);
315 ui_helpline__puts(self
->helpline
);
319 if (self
->use_navkeypressed
&& !self
->navkeypressed
) {
320 if (key
== K_DOWN
|| key
== K_UP
||
321 key
== K_PGDN
|| key
== K_PGUP
||
322 key
== K_HOME
|| key
== K_END
||
324 self
->navkeypressed
= true;
332 if (self
->index
== self
->nr_entries
- 1)
335 if (self
->index
== self
->top_idx
+ self
->height
) {
337 self
->seek(self
, +1, SEEK_CUR
);
341 if (self
->index
== 0)
344 if (self
->index
< self
->top_idx
) {
346 self
->seek(self
, -1, SEEK_CUR
);
351 if (self
->top_idx
+ self
->height
> self
->nr_entries
- 1)
354 offset
= self
->height
;
355 if (self
->index
+ offset
> self
->nr_entries
- 1)
356 offset
= self
->nr_entries
- 1 - self
->index
;
357 self
->index
+= offset
;
358 self
->top_idx
+= offset
;
359 self
->seek(self
, +offset
, SEEK_CUR
);
362 if (self
->top_idx
== 0)
365 if (self
->top_idx
< self
->height
)
366 offset
= self
->top_idx
;
368 offset
= self
->height
;
370 self
->index
-= offset
;
371 self
->top_idx
-= offset
;
372 self
->seek(self
, -offset
, SEEK_CUR
);
375 ui_browser__reset_index(self
);
378 offset
= self
->height
- 1;
379 if (offset
>= self
->nr_entries
)
380 offset
= self
->nr_entries
- 1;
382 self
->index
= self
->nr_entries
- 1;
383 self
->top_idx
= self
->index
- offset
;
384 self
->seek(self
, -offset
, SEEK_END
);
393 unsigned int ui_browser__list_head_refresh(struct ui_browser
*self
)
395 struct list_head
*pos
;
396 struct list_head
*head
= self
->entries
;
399 if (self
->top
== NULL
|| self
->top
== self
->entries
)
400 self
->top
= ui_browser__list_head_filter_entries(self
, head
->next
);
404 list_for_each_from(pos
, head
) {
405 if (!self
->filter
|| !self
->filter(self
, pos
)) {
406 ui_browser__gotorc(self
, row
, 0);
407 self
->write(self
, pos
, row
);
408 if (++row
== self
->height
)
416 static struct ui_browser__colorset
{
417 const char *name
, *fg
, *bg
;
419 } ui_browser__colorsets
[] = {
421 .colorset
= HE_COLORSET_TOP
,
427 .colorset
= HE_COLORSET_MEDIUM
,
433 .colorset
= HE_COLORSET_NORMAL
,
439 .colorset
= HE_COLORSET_SELECTED
,
445 .colorset
= HE_COLORSET_CODE
,
456 static int ui_browser__color_config(const char *var
, const char *value
,
459 char *fg
= NULL
, *bg
;
462 /* same dir for all commands */
463 if (prefixcmp(var
, "colors.") != 0)
466 for (i
= 0; ui_browser__colorsets
[i
].name
!= NULL
; ++i
) {
467 const char *name
= var
+ 7;
469 if (strcmp(ui_browser__colorsets
[i
].name
, name
) != 0)
476 bg
= strchr(fg
, ',');
481 while (isspace(*++bg
));
482 ui_browser__colorsets
[i
].bg
= bg
;
483 ui_browser__colorsets
[i
].fg
= fg
;
491 void ui_browser__init(void)
495 perf_config(ui_browser__color_config
, NULL
);
497 while (ui_browser__colorsets
[i
].name
) {
498 struct ui_browser__colorset
*c
= &ui_browser__colorsets
[i
++];
499 sltt_set_color(c
->colorset
, c
->name
, c
->fg
, c
->bg
);