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__handle_resize(struct ui_browser
*browser
)
174 ui__refresh_dimensions(false);
175 ui_browser__show(browser
, browser
->title
, ui_helpline__current
);
176 ui_browser__refresh(browser
);
179 int ui_browser__warning(struct ui_browser
*browser
, int timeout
,
180 const char *format
, ...)
186 va_start(args
, format
);
187 err
= vasprintf(&text
, format
, args
);
191 va_start(args
, format
);
192 ui_helpline__vpush(format
, args
);
195 while ((key
== ui__question_window("Warning!", text
,
197 timeout
)) == K_RESIZE
)
198 ui_browser__handle_resize(browser
);
205 int ui_browser__help_window(struct ui_browser
*browser
, const char *text
)
209 while ((key
= ui__help_window(text
)) == K_RESIZE
)
210 ui_browser__handle_resize(browser
);
215 bool ui_browser__dialog_yesno(struct ui_browser
*browser
, const char *text
)
219 while ((key
= ui__dialog_yesno(text
)) == K_RESIZE
)
220 ui_browser__handle_resize(browser
);
222 return key
== K_ENTER
|| toupper(key
) == 'Y';
225 void ui_browser__reset_index(struct ui_browser
*self
)
227 self
->index
= self
->top_idx
= 0;
228 self
->seek(self
, 0, SEEK_SET
);
231 void __ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
234 ui_browser__set_color(browser
, NEWT_COLORSET_ROOT
);
235 slsmg_write_nstring(title
, browser
->width
+ 1);
238 void ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
240 pthread_mutex_lock(&ui__lock
);
241 __ui_browser__show_title(browser
, title
);
242 pthread_mutex_unlock(&ui__lock
);
245 int ui_browser__show(struct ui_browser
*self
, const char *title
,
246 const char *helpline
, ...)
251 ui_browser__refresh_dimensions(self
);
253 pthread_mutex_lock(&ui__lock
);
254 __ui_browser__show_title(self
, title
);
257 free(self
->helpline
);
258 self
->helpline
= NULL
;
260 va_start(ap
, helpline
);
261 err
= vasprintf(&self
->helpline
, helpline
, ap
);
264 ui_helpline__push(self
->helpline
);
265 pthread_mutex_unlock(&ui__lock
);
269 void ui_browser__hide(struct ui_browser
*browser __used
)
271 pthread_mutex_lock(&ui__lock
);
273 pthread_mutex_unlock(&ui__lock
);
276 static void ui_browser__scrollbar_set(struct ui_browser
*browser
)
278 int height
= browser
->height
, h
= 0, pct
= 0,
279 col
= browser
->width
,
280 row
= browser
->y
- 1;
282 if (browser
->nr_entries
> 1) {
283 pct
= ((browser
->index
* (browser
->height
- 1)) /
284 (browser
->nr_entries
- 1));
287 SLsmg_set_char_set(1);
290 ui_browser__gotorc(browser
, row
++, col
);
291 SLsmg_write_char(h
== pct
? SLSMG_DIAMOND_CHAR
: SLSMG_CKBRD_CHAR
);
295 SLsmg_set_char_set(0);
298 static int __ui_browser__refresh(struct ui_browser
*browser
)
301 int width
= browser
->width
;
303 row
= browser
->refresh(browser
);
304 ui_browser__set_color(browser
, HE_COLORSET_NORMAL
);
306 if (!browser
->use_navkeypressed
|| browser
->navkeypressed
)
307 ui_browser__scrollbar_set(browser
);
311 SLsmg_fill_region(browser
->y
+ row
, browser
->x
,
312 browser
->height
- row
, width
, ' ');
317 int ui_browser__refresh(struct ui_browser
*browser
)
319 pthread_mutex_lock(&ui__lock
);
320 __ui_browser__refresh(browser
);
321 pthread_mutex_unlock(&ui__lock
);
327 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
328 * forget about any reference to any entry in the underlying data structure,
329 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
330 * after an output_resort and hist decay.
332 void ui_browser__update_nr_entries(struct ui_browser
*browser
, u32 nr_entries
)
334 off_t offset
= nr_entries
- browser
->nr_entries
;
336 browser
->nr_entries
= nr_entries
;
339 if (browser
->top_idx
< (u64
)-offset
)
340 offset
= -browser
->top_idx
;
342 browser
->index
+= offset
;
343 browser
->top_idx
+= offset
;
347 browser
->seek(browser
, browser
->top_idx
, SEEK_SET
);
350 int ui_browser__run(struct ui_browser
*self
, int delay_secs
)
357 pthread_mutex_lock(&ui__lock
);
358 err
= __ui_browser__refresh(self
);
360 pthread_mutex_unlock(&ui__lock
);
364 key
= ui__getch(delay_secs
);
366 if (key
== K_RESIZE
) {
367 ui__refresh_dimensions(false);
368 ui_browser__refresh_dimensions(self
);
369 __ui_browser__show_title(self
, self
->title
);
370 ui_helpline__puts(self
->helpline
);
374 if (self
->use_navkeypressed
&& !self
->navkeypressed
) {
375 if (key
== K_DOWN
|| key
== K_UP
||
376 key
== K_PGDN
|| key
== K_PGUP
||
377 key
== K_HOME
|| key
== K_END
||
379 self
->navkeypressed
= true;
387 if (self
->index
== self
->nr_entries
- 1)
390 if (self
->index
== self
->top_idx
+ self
->height
) {
392 self
->seek(self
, +1, SEEK_CUR
);
396 if (self
->index
== 0)
399 if (self
->index
< self
->top_idx
) {
401 self
->seek(self
, -1, SEEK_CUR
);
406 if (self
->top_idx
+ self
->height
> self
->nr_entries
- 1)
409 offset
= self
->height
;
410 if (self
->index
+ offset
> self
->nr_entries
- 1)
411 offset
= self
->nr_entries
- 1 - self
->index
;
412 self
->index
+= offset
;
413 self
->top_idx
+= offset
;
414 self
->seek(self
, +offset
, SEEK_CUR
);
417 if (self
->top_idx
== 0)
420 if (self
->top_idx
< self
->height
)
421 offset
= self
->top_idx
;
423 offset
= self
->height
;
425 self
->index
-= offset
;
426 self
->top_idx
-= offset
;
427 self
->seek(self
, -offset
, SEEK_CUR
);
430 ui_browser__reset_index(self
);
433 offset
= self
->height
- 1;
434 if (offset
>= self
->nr_entries
)
435 offset
= self
->nr_entries
- 1;
437 self
->index
= self
->nr_entries
- 1;
438 self
->top_idx
= self
->index
- offset
;
439 self
->seek(self
, -offset
, SEEK_END
);
448 unsigned int ui_browser__list_head_refresh(struct ui_browser
*self
)
450 struct list_head
*pos
;
451 struct list_head
*head
= self
->entries
;
454 if (self
->top
== NULL
|| self
->top
== self
->entries
)
455 self
->top
= ui_browser__list_head_filter_entries(self
, head
->next
);
459 list_for_each_from(pos
, head
) {
460 if (!self
->filter
|| !self
->filter(self
, pos
)) {
461 ui_browser__gotorc(self
, row
, 0);
462 self
->write(self
, pos
, row
);
463 if (++row
== self
->height
)
471 static struct ui_browser__colorset
{
472 const char *name
, *fg
, *bg
;
474 } ui_browser__colorsets
[] = {
476 .colorset
= HE_COLORSET_TOP
,
482 .colorset
= HE_COLORSET_MEDIUM
,
488 .colorset
= HE_COLORSET_NORMAL
,
494 .colorset
= HE_COLORSET_SELECTED
,
500 .colorset
= HE_COLORSET_CODE
,
511 static int ui_browser__color_config(const char *var
, const char *value
,
514 char *fg
= NULL
, *bg
;
517 /* same dir for all commands */
518 if (prefixcmp(var
, "colors.") != 0)
521 for (i
= 0; ui_browser__colorsets
[i
].name
!= NULL
; ++i
) {
522 const char *name
= var
+ 7;
524 if (strcmp(ui_browser__colorsets
[i
].name
, name
) != 0)
531 bg
= strchr(fg
, ',');
536 while (isspace(*++bg
));
537 ui_browser__colorsets
[i
].bg
= bg
;
538 ui_browser__colorsets
[i
].fg
= fg
;
546 void ui_browser__argv_seek(struct ui_browser
*browser
, off_t offset
, int whence
)
550 browser
->top
= browser
->entries
;
553 browser
->top
= browser
->top
+ browser
->top_idx
+ offset
;
556 browser
->top
= browser
->top
+ browser
->nr_entries
+ offset
;
563 unsigned int ui_browser__argv_refresh(struct ui_browser
*browser
)
565 unsigned int row
= 0, idx
= browser
->top_idx
;
568 if (browser
->top
== NULL
)
569 browser
->top
= browser
->entries
;
571 pos
= (char **)browser
->top
;
572 while (idx
< browser
->nr_entries
) {
573 if (!browser
->filter
|| !browser
->filter(browser
, *pos
)) {
574 ui_browser__gotorc(browser
, row
, 0);
575 browser
->write(browser
, pos
, row
);
576 if (++row
== browser
->height
)
587 void ui_browser__init(void)
591 perf_config(ui_browser__color_config
, NULL
);
593 while (ui_browser__colorsets
[i
].name
) {
594 struct ui_browser__colorset
*c
= &ui_browser__colorsets
[i
++];
595 sltt_set_color(c
->colorset
, c
->name
, c
->fg
, c
->bg
);