aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-08-06 16:35:02 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-08-06 20:50:41 -0400
commitef8f34aabf2450a9fb36b2c87fe0ea0b86a38195 (patch)
treeb819e0d5a895cb24c625cd357e10fbcd674a3335 /tools
parent43730982c3e9355dd8bd6b31f0a0a3508ad4209d (diff)
perf ui: Start breaking down newt.c into multiple files
As new TUI features get added the newt.c file is growing a lot and its name is growing misleading as an effort is being made to reduce the coupling with libnewt. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile10
-rw-r--r--tools/perf/util/newt.c306
-rw-r--r--tools/perf/util/ui/browser.c313
-rw-r--r--tools/perf/util/ui/browser.h43
4 files changed, 368 insertions, 304 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 26f626d45a9e..d5bce768b4bf 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -157,9 +157,8 @@ all::
157# 157#
158# Define NO_DWARF if you do not want debug-info analysis feature at all. 158# Define NO_DWARF if you do not want debug-info analysis feature at all.
159 159
160$(shell sh -c 'mkdir -p $(OUTPUT)scripts/python/Perf-Trace-Util/' 2> /dev/null) 160$(shell sh -c 'mkdir -p $(OUTPUT)scripts/{perl,python}/Perf-Trace-Util/' 2> /dev/null)
161$(shell sh -c 'mkdir -p $(OUTPUT)scripts/perl/Perf-Trace-Util/' 2> /dev/null) 161$(shell sh -c 'mkdir -p $(OUTPUT)util/{ui,scripting-engines}/' 2> /dev/null)
162$(shell sh -c 'mkdir -p $(OUTPUT)util/scripting-engines/' 2> /dev/null)
163$(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null) 162$(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null)
164 163
165$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 164$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
@@ -569,6 +568,8 @@ else
569 BASIC_CFLAGS += -I/usr/include/slang 568 BASIC_CFLAGS += -I/usr/include/slang
570 EXTLIBS += -lnewt -lslang 569 EXTLIBS += -lnewt -lslang
571 LIB_OBJS += $(OUTPUT)util/newt.o 570 LIB_OBJS += $(OUTPUT)util/newt.o
571 LIB_OBJS += $(OUTPUT)util/ui/browser.o
572 LIB_H += util/ui/browser.h
572 endif 573 endif
573endif 574endif
574 575
@@ -969,6 +970,9 @@ $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
969$(OUTPUT)util/newt.o: util/newt.c $(OUTPUT)PERF-CFLAGS 970$(OUTPUT)util/newt.o: util/newt.c $(OUTPUT)PERF-CFLAGS
970 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 971 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
971 972
973$(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
974 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
975
972$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 976$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
973 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 977 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
974 978
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 37fe8eb811ca..266a9e06525b 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -23,6 +23,7 @@
23#include "session.h" 23#include "session.h"
24#include "sort.h" 24#include "sort.h"
25#include "symbol.h" 25#include "symbol.h"
26#include "ui/browser.h"
26 27
27#if SLANG_VERSION < 20104 28#if SLANG_VERSION < 20104
28#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args) 29#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args)
@@ -35,6 +36,8 @@
35#define sltt_set_color SLtt_set_color 36#define sltt_set_color SLtt_set_color
36#endif 37#endif
37 38
39newtComponent newt_form__new(void);
40
38struct ui_progress { 41struct ui_progress {
39 newtComponent form, scale; 42 newtComponent form, scale;
40}; 43};
@@ -190,7 +193,7 @@ static void newt_form__set_exit_keys(newtComponent self)
190 newtFormAddHotKey(self, CTRL('c')); 193 newtFormAddHotKey(self, CTRL('c'));
191} 194}
192 195
193static newtComponent newt_form__new(void) 196newtComponent newt_form__new(void)
194{ 197{
195 newtComponent self = newtForm(NULL, NULL, 0); 198 newtComponent self = newtForm(NULL, NULL, 0);
196 if (self) 199 if (self)
@@ -290,172 +293,6 @@ static void ui__error_window(const char *fmt, ...)
290 va_end(ap); 293 va_end(ap);
291} 294}
292 295
293#define HE_COLORSET_TOP 50
294#define HE_COLORSET_MEDIUM 51
295#define HE_COLORSET_NORMAL 52
296#define HE_COLORSET_SELECTED 53
297#define HE_COLORSET_CODE 54
298
299static int ui_browser__percent_color(double percent, bool current)
300{
301 if (current)
302 return HE_COLORSET_SELECTED;
303 if (percent >= MIN_RED)
304 return HE_COLORSET_TOP;
305 if (percent >= MIN_GREEN)
306 return HE_COLORSET_MEDIUM;
307 return HE_COLORSET_NORMAL;
308}
309
310struct ui_browser {
311 newtComponent form, sb;
312 u64 index, first_visible_entry_idx;
313 void *first_visible_entry, *entries;
314 u16 top, left, width, height;
315 void *priv;
316 unsigned int (*refresh)(struct ui_browser *self);
317 void (*write)(struct ui_browser *self, void *entry, int row);
318 void (*seek)(struct ui_browser *self,
319 off_t offset, int whence);
320 u32 nr_entries;
321};
322
323static void ui_browser__list_head_seek(struct ui_browser *self,
324 off_t offset, int whence)
325{
326 struct list_head *head = self->entries;
327 struct list_head *pos;
328
329 switch (whence) {
330 case SEEK_SET:
331 pos = head->next;
332 break;
333 case SEEK_CUR:
334 pos = self->first_visible_entry;
335 break;
336 case SEEK_END:
337 pos = head->prev;
338 break;
339 default:
340 return;
341 }
342
343 if (offset > 0) {
344 while (offset-- != 0)
345 pos = pos->next;
346 } else {
347 while (offset++ != 0)
348 pos = pos->prev;
349 }
350
351 self->first_visible_entry = pos;
352}
353
354static void ui_browser__rb_tree_seek(struct ui_browser *self,
355 off_t offset, int whence)
356{
357 struct rb_root *root = self->entries;
358 struct rb_node *nd;
359
360 switch (whence) {
361 case SEEK_SET:
362 nd = rb_first(root);
363 break;
364 case SEEK_CUR:
365 nd = self->first_visible_entry;
366 break;
367 case SEEK_END:
368 nd = rb_last(root);
369 break;
370 default:
371 return;
372 }
373
374 if (offset > 0) {
375 while (offset-- != 0)
376 nd = rb_next(nd);
377 } else {
378 while (offset++ != 0)
379 nd = rb_prev(nd);
380 }
381
382 self->first_visible_entry = nd;
383}
384
385static unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
386{
387 struct rb_node *nd;
388 int row = 0;
389
390 if (self->first_visible_entry == NULL)
391 self->first_visible_entry = rb_first(self->entries);
392
393 nd = self->first_visible_entry;
394
395 while (nd != NULL) {
396 SLsmg_gotorc(self->top + row, self->left);
397 self->write(self, nd, row);
398 if (++row == self->height)
399 break;
400 nd = rb_next(nd);
401 }
402
403 return row;
404}
405
406static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
407{
408 return (self->first_visible_entry_idx + row) == self->index;
409}
410
411static void ui_browser__refresh_dimensions(struct ui_browser *self)
412{
413 int cols, rows;
414 newtGetScreenSize(&cols, &rows);
415
416 if (self->width > cols - 4)
417 self->width = cols - 4;
418 self->height = rows - 5;
419 if (self->height > self->nr_entries)
420 self->height = self->nr_entries;
421 self->top = (rows - self->height) / 2;
422 self->left = (cols - self->width) / 2;
423}
424
425static void ui_browser__reset_index(struct ui_browser *self)
426{
427 self->index = self->first_visible_entry_idx = 0;
428 self->seek(self, 0, SEEK_SET);
429}
430
431static int ui_browser__show(struct ui_browser *self, const char *title)
432{
433 if (self->form != NULL) {
434 newtFormDestroy(self->form);
435 newtPopWindow();
436 }
437 ui_browser__refresh_dimensions(self);
438 newtCenteredWindow(self->width, self->height, title);
439 self->form = newt_form__new();
440 if (self->form == NULL)
441 return -1;
442
443 self->sb = newtVerticalScrollbar(self->width, 0, self->height,
444 HE_COLORSET_NORMAL,
445 HE_COLORSET_SELECTED);
446 if (self->sb == NULL)
447 return -1;
448
449 newtFormAddHotKey(self->form, NEWT_KEY_UP);
450 newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
451 newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
452 newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
453 newtFormAddHotKey(self->form, NEWT_KEY_HOME);
454 newtFormAddHotKey(self->form, NEWT_KEY_END);
455 newtFormAddComponent(self->form, self->sb);
456 return 0;
457}
458
459static void annotate_browser__write(struct ui_browser *self, void *entry, int row) 296static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
460{ 297{
461 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); 298 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);
@@ -507,98 +344,6 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
507 slsmg_write_nstring(ol->line, width - 18); 344 slsmg_write_nstring(ol->line, width - 18);
508} 345}
509 346
510static int ui_browser__refresh(struct ui_browser *self)
511{
512 int row;
513
514 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
515 row = self->refresh(self);
516 SLsmg_set_color(HE_COLORSET_NORMAL);
517 SLsmg_fill_region(self->top + row, self->left,
518 self->height - row, self->width, ' ');
519
520 return 0;
521}
522
523static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
524{
525 if (ui_browser__refresh(self) < 0)
526 return -1;
527
528 while (1) {
529 off_t offset;
530
531 newtFormRun(self->form, es);
532
533 if (es->reason != NEWT_EXIT_HOTKEY)
534 break;
535 if (is_exit_key(es->u.key))
536 return es->u.key;
537 switch (es->u.key) {
538 case NEWT_KEY_DOWN:
539 if (self->index == self->nr_entries - 1)
540 break;
541 ++self->index;
542 if (self->index == self->first_visible_entry_idx + self->height) {
543 ++self->first_visible_entry_idx;
544 self->seek(self, +1, SEEK_CUR);
545 }
546 break;
547 case NEWT_KEY_UP:
548 if (self->index == 0)
549 break;
550 --self->index;
551 if (self->index < self->first_visible_entry_idx) {
552 --self->first_visible_entry_idx;
553 self->seek(self, -1, SEEK_CUR);
554 }
555 break;
556 case NEWT_KEY_PGDN:
557 case ' ':
558 if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
559 break;
560
561 offset = self->height;
562 if (self->index + offset > self->nr_entries - 1)
563 offset = self->nr_entries - 1 - self->index;
564 self->index += offset;
565 self->first_visible_entry_idx += offset;
566 self->seek(self, +offset, SEEK_CUR);
567 break;
568 case NEWT_KEY_PGUP:
569 if (self->first_visible_entry_idx == 0)
570 break;
571
572 if (self->first_visible_entry_idx < self->height)
573 offset = self->first_visible_entry_idx;
574 else
575 offset = self->height;
576
577 self->index -= offset;
578 self->first_visible_entry_idx -= offset;
579 self->seek(self, -offset, SEEK_CUR);
580 break;
581 case NEWT_KEY_HOME:
582 ui_browser__reset_index(self);
583 break;
584 case NEWT_KEY_END:
585 offset = self->height - 1;
586 if (offset >= self->nr_entries)
587 offset = self->nr_entries - 1;
588
589 self->index = self->nr_entries - 1;
590 self->first_visible_entry_idx = self->index - offset;
591 self->seek(self, -offset, SEEK_END);
592 break;
593 default:
594 return es->u.key;
595 }
596 if (ui_browser__refresh(self) < 0)
597 return -1;
598 }
599 return 0;
600}
601
602static char *callchain_list__sym_name(struct callchain_list *self, 347static char *callchain_list__sym_name(struct callchain_list *self,
603 char *bf, size_t bfsize) 348 char *bf, size_t bfsize)
604{ 349{
@@ -609,27 +354,6 @@ static char *callchain_list__sym_name(struct callchain_list *self,
609 return bf; 354 return bf;
610} 355}
611 356
612static unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
613{
614 struct list_head *pos;
615 struct list_head *head = self->entries;
616 int row = 0;
617
618 if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries)
619 self->first_visible_entry = head->next;
620
621 pos = self->first_visible_entry;
622
623 list_for_each_from(pos, head) {
624 SLsmg_gotorc(self->top + row, self->left);
625 self->write(self, pos, row);
626 if (++row == self->height)
627 break;
628 }
629
630 return row;
631}
632
633int hist_entry__tui_annotate(struct hist_entry *self) 357int hist_entry__tui_annotate(struct hist_entry *self)
634{ 358{
635 struct newtExitStruct es; 359 struct newtExitStruct es;
@@ -1093,20 +817,6 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help)
1093 return key; 817 return key;
1094} 818}
1095 819
1096static struct newtPercentTreeColors {
1097 const char *topColorFg, *topColorBg;
1098 const char *mediumColorFg, *mediumColorBg;
1099 const char *normalColorFg, *normalColorBg;
1100 const char *selColorFg, *selColorBg;
1101 const char *codeColorFg, *codeColorBg;
1102} defaultPercentTreeColors = {
1103 "red", "lightgray",
1104 "green", "lightgray",
1105 "black", "lightgray",
1106 "lightgray", "magenta",
1107 "blue", "lightgray",
1108};
1109
1110static void newt_suspend(void *d __used) 820static void newt_suspend(void *d __used)
1111{ 821{
1112 newtSuspend(); 822 newtSuspend();
@@ -1116,8 +826,6 @@ static void newt_suspend(void *d __used)
1116 826
1117void setup_browser(void) 827void setup_browser(void)
1118{ 828{
1119 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
1120
1121 if (!isatty(1) || !use_browser || dump_trace) { 829 if (!isatty(1) || !use_browser || dump_trace) {
1122 use_browser = 0; 830 use_browser = 0;
1123 setup_pager(); 831 setup_pager();
@@ -1129,11 +837,7 @@ void setup_browser(void)
1129 newtCls(); 837 newtCls();
1130 newtSetSuspendCallback(newt_suspend, NULL); 838 newtSetSuspendCallback(newt_suspend, NULL);
1131 ui_helpline__puts(" "); 839 ui_helpline__puts(" ");
1132 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); 840 ui_browser__init();
1133 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
1134 sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
1135 sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
1136 sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
1137} 841}
1138 842
1139void exit_browser(bool wait_for_ok) 843void exit_browser(bool wait_for_ok)
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
new file mode 100644
index 000000000000..0b2b9306312d
--- /dev/null
+++ b/tools/perf/util/ui/browser.c
@@ -0,0 +1,313 @@
1#define _GNU_SOURCE
2#include <stdio.h>
3#undef _GNU_SOURCE
4/*
5 * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
6 * the build if it isn't defined. Use the equivalent one that glibc
7 * has on features.h.
8 */
9#include <features.h>
10#ifndef HAVE_LONG_LONG
11#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
12#endif
13#include <slang.h>
14#include <linux/list.h>
15#include <linux/rbtree.h>
16#include <stdlib.h>
17#include <sys/ttydefaults.h>
18#include "browser.h"
19#include "../color.h"
20#include "../util.h"
21
22#if SLANG_VERSION < 20104
23#define sltt_set_color(obj, name, fg, bg) \
24 SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
25#else
26#define sltt_set_color SLtt_set_color
27#endif
28
29newtComponent newt_form__new(void);
30
31int ui_browser__percent_color(double percent, bool current)
32{
33 if (current)
34 return HE_COLORSET_SELECTED;
35 if (percent >= MIN_RED)
36 return HE_COLORSET_TOP;
37 if (percent >= MIN_GREEN)
38 return HE_COLORSET_MEDIUM;
39 return HE_COLORSET_NORMAL;
40}
41
42void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
43{
44 struct list_head *head = self->entries;
45 struct list_head *pos;
46
47 switch (whence) {
48 case SEEK_SET:
49 pos = head->next;
50 break;
51 case SEEK_CUR:
52 pos = self->first_visible_entry;
53 break;
54 case SEEK_END:
55 pos = head->prev;
56 break;
57 default:
58 return;
59 }
60
61 if (offset > 0) {
62 while (offset-- != 0)
63 pos = pos->next;
64 } else {
65 while (offset++ != 0)
66 pos = pos->prev;
67 }
68
69 self->first_visible_entry = pos;
70}
71
72void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
73{
74 struct rb_root *root = self->entries;
75 struct rb_node *nd;
76
77 switch (whence) {
78 case SEEK_SET:
79 nd = rb_first(root);
80 break;
81 case SEEK_CUR:
82 nd = self->first_visible_entry;
83 break;
84 case SEEK_END:
85 nd = rb_last(root);
86 break;
87 default:
88 return;
89 }
90
91 if (offset > 0) {
92 while (offset-- != 0)
93 nd = rb_next(nd);
94 } else {
95 while (offset++ != 0)
96 nd = rb_prev(nd);
97 }
98
99 self->first_visible_entry = nd;
100}
101
102unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
103{
104 struct rb_node *nd;
105 int row = 0;
106
107 if (self->first_visible_entry == NULL)
108 self->first_visible_entry = rb_first(self->entries);
109
110 nd = self->first_visible_entry;
111
112 while (nd != NULL) {
113 SLsmg_gotorc(self->top + row, self->left);
114 self->write(self, nd, row);
115 if (++row == self->height)
116 break;
117 nd = rb_next(nd);
118 }
119
120 return row;
121}
122
123bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
124{
125 return (self->first_visible_entry_idx + row) == self->index;
126}
127
128void ui_browser__refresh_dimensions(struct ui_browser *self)
129{
130 int cols, rows;
131 newtGetScreenSize(&cols, &rows);
132
133 if (self->width > cols - 4)
134 self->width = cols - 4;
135 self->height = rows - 5;
136 if (self->height > self->nr_entries)
137 self->height = self->nr_entries;
138 self->top = (rows - self->height) / 2;
139 self->left = (cols - self->width) / 2;
140}
141
142void ui_browser__reset_index(struct ui_browser *self)
143{
144 self->index = self->first_visible_entry_idx = 0;
145 self->seek(self, 0, SEEK_SET);
146}
147
148int ui_browser__show(struct ui_browser *self, const char *title)
149{
150 if (self->form != NULL) {
151 newtFormDestroy(self->form);
152 newtPopWindow();
153 }
154 ui_browser__refresh_dimensions(self);
155 newtCenteredWindow(self->width, self->height, title);
156 self->form = newt_form__new();
157 if (self->form == NULL)
158 return -1;
159
160 self->sb = newtVerticalScrollbar(self->width, 0, self->height,
161 HE_COLORSET_NORMAL,
162 HE_COLORSET_SELECTED);
163 if (self->sb == NULL)
164 return -1;
165
166 newtFormAddHotKey(self->form, NEWT_KEY_UP);
167 newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
168 newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
169 newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
170 newtFormAddHotKey(self->form, NEWT_KEY_HOME);
171 newtFormAddHotKey(self->form, NEWT_KEY_END);
172 newtFormAddComponent(self->form, self->sb);
173 return 0;
174}
175
176int ui_browser__refresh(struct ui_browser *self)
177{
178 int row;
179
180 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
181 row = self->refresh(self);
182 SLsmg_set_color(HE_COLORSET_NORMAL);
183 SLsmg_fill_region(self->top + row, self->left,
184 self->height - row, self->width, ' ');
185
186 return 0;
187}
188
189int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
190{
191 if (ui_browser__refresh(self) < 0)
192 return -1;
193
194 while (1) {
195 off_t offset;
196
197 newtFormRun(self->form, es);
198
199 if (es->reason != NEWT_EXIT_HOTKEY)
200 break;
201 if (is_exit_key(es->u.key))
202 return es->u.key;
203 switch (es->u.key) {
204 case NEWT_KEY_DOWN:
205 if (self->index == self->nr_entries - 1)
206 break;
207 ++self->index;
208 if (self->index == self->first_visible_entry_idx + self->height) {
209 ++self->first_visible_entry_idx;
210 self->seek(self, +1, SEEK_CUR);
211 }
212 break;
213 case NEWT_KEY_UP:
214 if (self->index == 0)
215 break;
216 --self->index;
217 if (self->index < self->first_visible_entry_idx) {
218 --self->first_visible_entry_idx;
219 self->seek(self, -1, SEEK_CUR);
220 }
221 break;
222 case NEWT_KEY_PGDN:
223 case ' ':
224 if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
225 break;
226
227 offset = self->height;
228 if (self->index + offset > self->nr_entries - 1)
229 offset = self->nr_entries - 1 - self->index;
230 self->index += offset;
231 self->first_visible_entry_idx += offset;
232 self->seek(self, +offset, SEEK_CUR);
233 break;
234 case NEWT_KEY_PGUP:
235 if (self->first_visible_entry_idx == 0)
236 break;
237
238 if (self->first_visible_entry_idx < self->height)
239 offset = self->first_visible_entry_idx;
240 else
241 offset = self->height;
242
243 self->index -= offset;
244 self->first_visible_entry_idx -= offset;
245 self->seek(self, -offset, SEEK_CUR);
246 break;
247 case NEWT_KEY_HOME:
248 ui_browser__reset_index(self);
249 break;
250 case NEWT_KEY_END:
251 offset = self->height - 1;
252 if (offset >= self->nr_entries)
253 offset = self->nr_entries - 1;
254
255 self->index = self->nr_entries - 1;
256 self->first_visible_entry_idx = self->index - offset;
257 self->seek(self, -offset, SEEK_END);
258 break;
259 default:
260 return es->u.key;
261 }
262 if (ui_browser__refresh(self) < 0)
263 return -1;
264 }
265 return 0;
266}
267
268unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
269{
270 struct list_head *pos;
271 struct list_head *head = self->entries;
272 int row = 0;
273
274 if (self->first_visible_entry == NULL ||
275 self->first_visible_entry == self->entries)
276 self->first_visible_entry = head->next;
277
278 pos = self->first_visible_entry;
279
280 list_for_each_from(pos, head) {
281 SLsmg_gotorc(self->top + row, self->left);
282 self->write(self, pos, row);
283 if (++row == self->height)
284 break;
285 }
286
287 return row;
288}
289
290static struct newtPercentTreeColors {
291 const char *topColorFg, *topColorBg;
292 const char *mediumColorFg, *mediumColorBg;
293 const char *normalColorFg, *normalColorBg;
294 const char *selColorFg, *selColorBg;
295 const char *codeColorFg, *codeColorBg;
296} defaultPercentTreeColors = {
297 "red", "lightgray",
298 "green", "lightgray",
299 "black", "lightgray",
300 "lightgray", "magenta",
301 "blue", "lightgray",
302};
303
304void ui_browser__init(void)
305{
306 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
307
308 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
309 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
310 sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
311 sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
312 sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
313}
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
new file mode 100644
index 000000000000..bcc4391405bd
--- /dev/null
+++ b/tools/perf/util/ui/browser.h
@@ -0,0 +1,43 @@
1#ifndef _PERF_UI_BROWSER_H_
2#define _PERF_UI_BROWSER_H_ 1
3
4#include <stdbool.h>
5#include <newt.h>
6#include "../types.h"
7
8#define HE_COLORSET_TOP 50
9#define HE_COLORSET_MEDIUM 51
10#define HE_COLORSET_NORMAL 52
11#define HE_COLORSET_SELECTED 53
12#define HE_COLORSET_CODE 54
13
14struct ui_browser {
15 newtComponent form, sb;
16 u64 index, first_visible_entry_idx;
17 void *first_visible_entry, *entries;
18 u16 top, left, width, height;
19 void *priv;
20 unsigned int (*refresh)(struct ui_browser *self);
21 void (*write)(struct ui_browser *self, void *entry, int row);
22 void (*seek)(struct ui_browser *self, off_t offset, int whence);
23 u32 nr_entries;
24};
25
26
27int ui_browser__percent_color(double percent, bool current);
28bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
29void ui_browser__refresh_dimensions(struct ui_browser *self);
30void ui_browser__reset_index(struct ui_browser *self);
31
32int ui_browser__show(struct ui_browser *self, const char *title);
33int ui_browser__refresh(struct ui_browser *self);
34int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es);
35
36void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
37unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
38
39void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence);
40unsigned int ui_browser__list_head_refresh(struct ui_browser *self);
41
42void ui_browser__init(void);
43#endif /* _PERF_UI_BROWSER_H_ */