2 #include "../../perf.h"
6 #include <linux/compiler.h>
7 #include <linux/list.h>
8 #include <linux/rbtree.h>
10 #include <sys/ttydefaults.h>
17 static int ui_browser__percent_color(double percent
, bool current
)
20 return HE_COLORSET_SELECTED
;
21 if (percent
>= MIN_RED
)
22 return HE_COLORSET_TOP
;
23 if (percent
>= MIN_GREEN
)
24 return HE_COLORSET_MEDIUM
;
25 return HE_COLORSET_NORMAL
;
28 void ui_browser__set_color(struct ui_browser
*self __used
, int color
)
30 SLsmg_set_color(color
);
33 void ui_browser__set_percent_color(struct ui_browser
*self
,
34 double percent
, bool current
)
36 int color
= ui_browser__percent_color(percent
, current
);
37 ui_browser__set_color(self
, color
);
40 void ui_browser__gotorc(struct ui_browser
*self
, int y
, int x
)
42 SLsmg_gotorc(self
->y
+ y
, self
->x
+ x
);
45 void ui_browser__list_head_seek(struct ui_browser
*self
, off_t offset
, int whence
)
47 struct list_head
*head
= self
->entries
;
48 struct list_head
*pos
;
75 void ui_browser__rb_tree_seek(struct ui_browser
*self
, off_t offset
, int whence
)
77 struct rb_root
*root
= self
->entries
;
105 unsigned int ui_browser__rb_tree_refresh(struct ui_browser
*self
)
110 if (self
->top
== NULL
)
111 self
->top
= rb_first(self
->entries
);
116 ui_browser__gotorc(self
, row
, 0);
117 self
->write(self
, nd
, row
);
118 if (++row
== self
->height
)
126 bool ui_browser__is_current_entry(struct ui_browser
*self
, unsigned row
)
128 return self
->top_idx
+ row
== self
->index
;
131 void ui_browser__refresh_dimensions(struct ui_browser
*self
)
133 self
->width
= SLtt_Screen_Cols
- 1;
134 self
->height
= SLtt_Screen_Rows
- 2;
139 void ui_browser__reset_index(struct ui_browser
*self
)
141 self
->index
= self
->top_idx
= 0;
142 self
->seek(self
, 0, SEEK_SET
);
145 void ui_browser__add_exit_key(struct ui_browser
*browser __used
, int key __used
)
149 void ui_browser__add_exit_keys(struct ui_browser
*self
, int keys
[])
153 while (keys
[i
] && i
< 64) {
154 ui_browser__add_exit_key(self
, keys
[i
]);
159 void __ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
162 ui_browser__set_color(browser
, NEWT_COLORSET_ROOT
);
163 slsmg_write_nstring(title
, browser
->width
+ 1);
166 void ui_browser__show_title(struct ui_browser
*browser
, const char *title
)
168 pthread_mutex_lock(&ui__lock
);
169 __ui_browser__show_title(browser
, title
);
170 pthread_mutex_unlock(&ui__lock
);
173 int ui_browser__show(struct ui_browser
*self
, const char *title
,
174 const char *helpline
, ...)
178 int keys
[] = { NEWT_KEY_UP
, NEWT_KEY_DOWN
, NEWT_KEY_PGUP
,
179 NEWT_KEY_PGDN
, NEWT_KEY_HOME
, NEWT_KEY_END
, ' ',
180 NEWT_KEY_LEFT
, NEWT_KEY_ESCAPE
, 'q', CTRL('c'), 0 };
182 ui_browser__refresh_dimensions(self
);
184 pthread_mutex_lock(&ui__lock
);
185 __ui_browser__show_title(self
, title
);
187 ui_browser__add_exit_keys(self
, keys
);
189 free(self
->helpline
);
190 self
->helpline
= NULL
;
192 va_start(ap
, helpline
);
193 err
= vasprintf(&self
->helpline
, helpline
, ap
);
196 ui_helpline__push(self
->helpline
);
197 pthread_mutex_unlock(&ui__lock
);
201 void ui_browser__hide(struct ui_browser
*browser __used
)
203 pthread_mutex_lock(&ui__lock
);
205 pthread_mutex_unlock(&ui__lock
);
208 static void ui_browser__scrollbar_set(struct ui_browser
*browser
)
210 int height
= browser
->height
, h
= 0, pct
= 0,
211 col
= browser
->width
,
212 row
= browser
->y
- 1;
214 if (browser
->nr_entries
> 1) {
215 pct
= ((browser
->index
* (browser
->height
- 1)) /
216 (browser
->nr_entries
- 1));
220 ui_browser__gotorc(browser
, row
++, col
);
221 SLsmg_set_char_set(1);
222 SLsmg_write_char(h
== pct
? SLSMG_DIAMOND_CHAR
: SLSMG_BOARD_CHAR
);
223 SLsmg_set_char_set(0);
228 static int __ui_browser__refresh(struct ui_browser
*browser
)
232 row
= browser
->refresh(browser
);
233 ui_browser__set_color(browser
, HE_COLORSET_NORMAL
);
234 SLsmg_fill_region(browser
->y
+ row
, browser
->x
,
235 browser
->height
- row
, browser
->width
, ' ');
236 ui_browser__scrollbar_set(browser
);
241 int ui_browser__refresh(struct ui_browser
*browser
)
243 pthread_mutex_lock(&ui__lock
);
244 __ui_browser__refresh(browser
);
245 pthread_mutex_unlock(&ui__lock
);
251 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
252 * forget about any reference to any entry in the underlying data structure,
253 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
254 * after an output_resort and hist decay.
256 void ui_browser__update_nr_entries(struct ui_browser
*browser
, u32 nr_entries
)
258 off_t offset
= nr_entries
- browser
->nr_entries
;
260 browser
->nr_entries
= nr_entries
;
263 if (browser
->top_idx
< (u64
)-offset
)
264 offset
= -browser
->top_idx
;
266 browser
->index
+= offset
;
267 browser
->top_idx
+= offset
;
270 browser
->seek(browser
, browser
->top_idx
, SEEK_SET
);
273 int ui_browser__run(struct ui_browser
*self
, int delay_secs
)
276 struct timeval timeout
, *ptimeout
= delay_secs
? &timeout
: NULL
;
278 pthread__unblock_sigwinch();
284 pthread_mutex_lock(&ui__lock
);
285 err
= __ui_browser__refresh(self
);
287 pthread_mutex_unlock(&ui__lock
);
292 FD_SET(0, &read_set
);
295 timeout
.tv_sec
= delay_secs
;
299 err
= select(1, &read_set
, NULL
, NULL
, ptimeout
);
300 if (err
> 0 && FD_ISSET(0, &read_set
))
305 pthread_mutex_lock(&ui__lock
);
306 SLtt_get_screen_size();
308 pthread_mutex_unlock(&ui__lock
);
309 ui_browser__refresh_dimensions(self
);
310 __ui_browser__show_title(self
, self
->title
);
311 ui_helpline__puts(self
->helpline
);
317 if (self
->index
== self
->nr_entries
- 1)
320 if (self
->index
== self
->top_idx
+ self
->height
) {
322 self
->seek(self
, +1, SEEK_CUR
);
326 if (self
->index
== 0)
329 if (self
->index
< self
->top_idx
) {
331 self
->seek(self
, -1, SEEK_CUR
);
336 if (self
->top_idx
+ self
->height
> self
->nr_entries
- 1)
339 offset
= self
->height
;
340 if (self
->index
+ offset
> self
->nr_entries
- 1)
341 offset
= self
->nr_entries
- 1 - self
->index
;
342 self
->index
+= offset
;
343 self
->top_idx
+= offset
;
344 self
->seek(self
, +offset
, SEEK_CUR
);
347 if (self
->top_idx
== 0)
350 if (self
->top_idx
< self
->height
)
351 offset
= self
->top_idx
;
353 offset
= self
->height
;
355 self
->index
-= offset
;
356 self
->top_idx
-= offset
;
357 self
->seek(self
, -offset
, SEEK_CUR
);
360 ui_browser__reset_index(self
);
363 offset
= self
->height
- 1;
364 if (offset
>= self
->nr_entries
)
365 offset
= self
->nr_entries
- 1;
367 self
->index
= self
->nr_entries
- 1;
368 self
->top_idx
= self
->index
- offset
;
369 self
->seek(self
, -offset
, SEEK_END
);
378 unsigned int ui_browser__list_head_refresh(struct ui_browser
*self
)
380 struct list_head
*pos
;
381 struct list_head
*head
= self
->entries
;
384 if (self
->top
== NULL
|| self
->top
== self
->entries
)
385 self
->top
= head
->next
;
389 list_for_each_from(pos
, head
) {
390 ui_browser__gotorc(self
, row
, 0);
391 self
->write(self
, pos
, row
);
392 if (++row
== self
->height
)
399 static struct ui_browser__colors
{
400 const char *topColorFg
, *topColorBg
;
401 const char *mediumColorFg
, *mediumColorBg
;
402 const char *normalColorFg
, *normalColorBg
;
403 const char *selColorFg
, *selColorBg
;
404 const char *codeColorFg
, *codeColorBg
;
405 } ui_browser__default_colors
= {
407 "green", "lightgray",
408 "black", "lightgray",
409 "lightgray", "magenta",
413 void ui_browser__init(void)
415 struct ui_browser__colors
*c
= &ui_browser__default_colors
;
417 sltt_set_color(HE_COLORSET_TOP
, NULL
, c
->topColorFg
, c
->topColorBg
);
418 sltt_set_color(HE_COLORSET_MEDIUM
, NULL
, c
->mediumColorFg
, c
->mediumColorBg
);
419 sltt_set_color(HE_COLORSET_NORMAL
, NULL
, c
->normalColorFg
, c
->normalColorBg
);
420 sltt_set_color(HE_COLORSET_SELECTED
, NULL
, c
->selColorFg
, c
->selColorBg
);
421 sltt_set_color(HE_COLORSET_CODE
, NULL
, c
->codeColorFg
, c
->codeColorBg
);