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
10 #ifndef HAVE_LONG_LONG
11 #define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
16 #include <sys/ttydefaults.h>
25 #if SLANG_VERSION < 20104
26 #define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args)
27 #define slsmg_write_nstring(msg, len) SLsmg_write_nstring((char *)msg, len)
28 #define sltt_set_color(obj, name, fg, bg) SLtt_set_color(obj,(char *)name,\
29 (char *)fg, (char *)bg)
31 #define slsmg_printf SLsmg_printf
32 #define slsmg_write_nstring SLsmg_write_nstring
33 #define sltt_set_color SLtt_set_color
37 newtComponent form
, scale
;
40 struct ui_progress
*ui_progress__new(const char *title
, u64 total
)
42 struct ui_progress
*self
= malloc(sizeof(*self
));
46 newtGetScreenSize(&cols
, NULL
);
48 newtCenteredWindow(cols
, 1, title
);
49 self
->form
= newtForm(NULL
, NULL
, 0);
50 if (self
->form
== NULL
)
52 self
->scale
= newtScale(0, 0, cols
, total
);
53 if (self
->scale
== NULL
)
55 newtFormAddComponent(self
->form
, self
->scale
);
62 newtFormDestroy(self
->form
);
68 void ui_progress__update(struct ui_progress
*self
, u64 curr
)
70 newtScaleSet(self
->scale
, curr
);
74 void ui_progress__delete(struct ui_progress
*self
)
76 newtFormDestroy(self
->form
);
81 static void ui_helpline__pop(void)
86 static void ui_helpline__push(const char *msg
)
88 newtPushHelpLine(msg
);
91 static void ui_helpline__vpush(const char *fmt
, va_list ap
)
95 if (vasprintf(&s
, fmt
, ap
) < 0)
96 vfprintf(stderr
, fmt
, ap
);
103 static void ui_helpline__fpush(const char *fmt
, ...)
108 ui_helpline__vpush(fmt
, ap
);
112 static void ui_helpline__puts(const char *msg
)
115 ui_helpline__push(msg
);
118 static char browser__last_msg
[1024];
120 int browser__show_help(const char *format
, va_list ap
)
125 ret
= vsnprintf(browser__last_msg
+ backlog
,
126 sizeof(browser__last_msg
) - backlog
, format
, ap
);
129 if (browser__last_msg
[backlog
- 1] == '\n') {
130 ui_helpline__puts(browser__last_msg
);
138 static void newt_form__set_exit_keys(newtComponent self
)
140 newtFormAddHotKey(self
, NEWT_KEY_LEFT
);
141 newtFormAddHotKey(self
, NEWT_KEY_ESCAPE
);
142 newtFormAddHotKey(self
, 'Q');
143 newtFormAddHotKey(self
, 'q');
144 newtFormAddHotKey(self
, CTRL('c'));
147 static newtComponent
newt_form__new(void)
149 newtComponent self
= newtForm(NULL
, NULL
, 0);
151 newt_form__set_exit_keys(self
);
155 static int popup_menu(int argc
, char * const argv
[])
157 struct newtExitStruct es
;
158 int i
, rc
= -1, max_len
= 5;
159 newtComponent listbox
, form
= newt_form__new();
164 listbox
= newtListbox(0, 0, argc
, NEWT_FLAG_RETURNEXIT
);
166 goto out_destroy_form
;
168 newtFormAddComponent(form
, listbox
);
170 for (i
= 0; i
< argc
; ++i
) {
171 int len
= strlen(argv
[i
]);
174 if (newtListboxAddEntry(listbox
, argv
[i
], (void *)(long)i
))
175 goto out_destroy_form
;
178 newtCenteredWindow(max_len
, argc
, NULL
);
179 newtFormRun(form
, &es
);
180 rc
= newtListboxGetCurrent(listbox
) - NULL
;
181 if (es
.reason
== NEWT_EXIT_HOTKEY
)
185 newtFormDestroy(form
);
189 static int ui__help_window(const char *text
)
191 struct newtExitStruct es
;
192 newtComponent tb
, form
= newt_form__new();
194 int max_len
= 0, nr_lines
= 0;
202 const char *sep
= strchr(t
, '\n');
206 sep
= strchr(t
, '\0');
216 tb
= newtTextbox(0, 0, max_len
, nr_lines
, 0);
218 goto out_destroy_form
;
220 newtTextboxSetText(tb
, text
);
221 newtFormAddComponent(form
, tb
);
222 newtCenteredWindow(max_len
, nr_lines
, NULL
);
223 newtFormRun(form
, &es
);
227 newtFormDestroy(form
);
231 static bool dialog_yesno(const char *msg
)
233 /* newtWinChoice should really be accepting const char pointers... */
234 char yes
[] = "Yes", no
[] = "No";
235 return newtWinChoice(NULL
, yes
, no
, (char *)msg
) == 1;
238 #define HE_COLORSET_TOP 50
239 #define HE_COLORSET_MEDIUM 51
240 #define HE_COLORSET_NORMAL 52
241 #define HE_COLORSET_SELECTED 53
242 #define HE_COLORSET_CODE 54
244 static int ui_browser__percent_color(double percent
, bool current
)
247 return HE_COLORSET_SELECTED
;
248 if (percent
>= MIN_RED
)
249 return HE_COLORSET_TOP
;
250 if (percent
>= MIN_GREEN
)
251 return HE_COLORSET_MEDIUM
;
252 return HE_COLORSET_NORMAL
;
256 newtComponent form
, sb
;
257 u64 index
, first_visible_entry_idx
;
258 void *first_visible_entry
, *entries
;
259 u16 top
, left
, width
, height
;
264 static void ui_browser__refresh_dimensions(struct ui_browser
*self
)
267 newtGetScreenSize(&cols
, &rows
);
269 if (self
->width
> cols
- 4)
270 self
->width
= cols
- 4;
271 self
->height
= rows
- 5;
272 if (self
->height
> self
->nr_entries
)
273 self
->height
= self
->nr_entries
;
274 self
->top
= (rows
- self
->height
) / 2;
275 self
->left
= (cols
- self
->width
) / 2;
278 static void ui_browser__reset_index(struct ui_browser
*self
)
280 self
->index
= self
->first_visible_entry_idx
= 0;
281 self
->first_visible_entry
= NULL
;
284 static int objdump_line__show(struct objdump_line
*self
, struct list_head
*head
,
285 int width
, struct hist_entry
*he
, int len
,
288 if (self
->offset
!= -1) {
289 struct symbol
*sym
= he
->ms
.sym
;
290 unsigned int hits
= 0;
291 double percent
= 0.0;
293 struct sym_priv
*priv
= symbol__priv(sym
);
294 struct sym_ext
*sym_ext
= priv
->ext
;
295 struct sym_hist
*h
= priv
->hist
;
296 s64 offset
= self
->offset
;
297 struct objdump_line
*next
= objdump__get_next_ip_line(head
, self
);
299 while (offset
< (s64
)len
&&
300 (next
== NULL
|| offset
< next
->offset
)) {
302 percent
+= sym_ext
[offset
].percent
;
304 hits
+= h
->ip
[offset
];
309 if (sym_ext
== NULL
&& h
->sum
)
310 percent
= 100.0 * hits
/ h
->sum
;
312 color
= ui_browser__percent_color(percent
, current_entry
);
313 SLsmg_set_color(color
);
314 slsmg_printf(" %7.2f ", percent
);
316 SLsmg_set_color(HE_COLORSET_CODE
);
318 int color
= ui_browser__percent_color(0, current_entry
);
319 SLsmg_set_color(color
);
320 slsmg_write_nstring(" ", 9);
323 SLsmg_write_char(':');
324 slsmg_write_nstring(" ", 8);
326 slsmg_write_nstring(" ", width
- 18);
328 slsmg_write_nstring(self
->line
, width
- 18);
333 static int ui_browser__refresh_entries(struct ui_browser
*self
)
335 struct objdump_line
*pos
;
336 struct list_head
*head
= self
->entries
;
337 struct hist_entry
*he
= self
->priv
;
339 int len
= he
->ms
.sym
->end
- he
->ms
.sym
->start
;
341 if (self
->first_visible_entry
== NULL
|| self
->first_visible_entry
== self
->entries
)
342 self
->first_visible_entry
= head
->next
;
344 pos
= list_entry(self
->first_visible_entry
, struct objdump_line
, node
);
346 list_for_each_entry_from(pos
, head
, node
) {
347 bool current_entry
= (self
->first_visible_entry_idx
+ row
) == self
->index
;
348 SLsmg_gotorc(self
->top
+ row
, self
->left
);
349 objdump_line__show(pos
, head
, self
->width
,
350 he
, len
, current_entry
);
351 if (++row
== self
->height
)
355 SLsmg_set_color(HE_COLORSET_NORMAL
);
356 SLsmg_fill_region(self
->top
+ row
, self
->left
,
357 self
->height
- row
, self
->width
, ' ');
362 static int ui_browser__run(struct ui_browser
*self
, const char *title
,
363 struct newtExitStruct
*es
)
366 newtFormDestroy(self
->form
);
370 ui_browser__refresh_dimensions(self
);
371 newtCenteredWindow(self
->width
+ 2, self
->height
, title
);
372 self
->form
= newt_form__new();
373 if (self
->form
== NULL
)
376 self
->sb
= newtVerticalScrollbar(self
->width
+ 1, 0, self
->height
,
378 HE_COLORSET_SELECTED
);
379 if (self
->sb
== NULL
)
382 newtFormAddHotKey(self
->form
, NEWT_KEY_UP
);
383 newtFormAddHotKey(self
->form
, NEWT_KEY_DOWN
);
384 newtFormAddHotKey(self
->form
, NEWT_KEY_PGUP
);
385 newtFormAddHotKey(self
->form
, NEWT_KEY_PGDN
);
386 newtFormAddHotKey(self
->form
, NEWT_KEY_HOME
);
387 newtFormAddHotKey(self
->form
, NEWT_KEY_END
);
389 if (ui_browser__refresh_entries(self
) < 0)
391 newtFormAddComponent(self
->form
, self
->sb
);
396 newtFormRun(self
->form
, es
);
398 if (es
->reason
!= NEWT_EXIT_HOTKEY
)
402 if (self
->index
== self
->nr_entries
- 1)
405 if (self
->index
== self
->first_visible_entry_idx
+ self
->height
) {
406 struct list_head
*pos
= self
->first_visible_entry
;
407 ++self
->first_visible_entry_idx
;
408 self
->first_visible_entry
= pos
->next
;
412 if (self
->index
== 0)
415 if (self
->index
< self
->first_visible_entry_idx
) {
416 struct list_head
*pos
= self
->first_visible_entry
;
417 --self
->first_visible_entry_idx
;
418 self
->first_visible_entry
= pos
->prev
;
422 if (self
->first_visible_entry_idx
+ self
->height
> self
->nr_entries
- 1)
425 offset
= self
->height
;
426 if (self
->index
+ offset
> self
->nr_entries
- 1)
427 offset
= self
->nr_entries
- 1 - self
->index
;
428 self
->index
+= offset
;
429 self
->first_visible_entry_idx
+= offset
;
432 struct list_head
*pos
= self
->first_visible_entry
;
433 self
->first_visible_entry
= pos
->next
;
438 if (self
->first_visible_entry_idx
== 0)
441 if (self
->first_visible_entry_idx
< self
->height
)
442 offset
= self
->first_visible_entry_idx
;
444 offset
= self
->height
;
446 self
->index
-= offset
;
447 self
->first_visible_entry_idx
-= offset
;
450 struct list_head
*pos
= self
->first_visible_entry
;
451 self
->first_visible_entry
= pos
->prev
;
455 ui_browser__reset_index(self
);
458 struct list_head
*head
= self
->entries
;
459 offset
= self
->height
- 1;
461 if (offset
> self
->nr_entries
)
462 offset
= self
->nr_entries
;
464 self
->index
= self
->first_visible_entry_idx
= self
->nr_entries
- 1 - offset
;
465 self
->first_visible_entry
= head
->prev
;
466 while (offset
-- != 0) {
467 struct list_head
*pos
= self
->first_visible_entry
;
468 self
->first_visible_entry
= pos
->prev
;
472 case NEWT_KEY_ESCAPE
:
481 if (ui_browser__refresh_entries(self
) < 0)
488 * When debugging newt problems it was useful to be able to "unroll"
489 * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate
490 * a source file with the sequence of calls to these methods, to then
491 * tweak the arrays to get the intended results, so I'm keeping this code
492 * here, may be useful again in the future.
496 static void newt_checkbox_tree__add(newtComponent tree
, const char *str
,
497 void *priv
, int *indexes
)
500 /* Print the newtCheckboxTreeAddArray to tinker with its index arrays */
501 int i
= 0, len
= 40 - strlen(str
);
504 "\tnewtCheckboxTreeAddItem(tree, %*.*s\"%s\", (void *)%p, 0, ",
505 len
, len
, " ", str
, priv
);
506 while (indexes
[i
] != NEWT_ARG_LAST
) {
507 if (indexes
[i
] != NEWT_ARG_APPEND
)
508 fprintf(stderr
, " %d,", indexes
[i
]);
510 fprintf(stderr
, " %s,", "NEWT_ARG_APPEND");
513 fprintf(stderr
, " %s", " NEWT_ARG_LAST);\n");
516 newtCheckboxTreeAddArray(tree
, str
, priv
, 0, indexes
);
519 static char *callchain_list__sym_name(struct callchain_list
*self
,
520 char *bf
, size_t bfsize
)
523 return self
->ms
.sym
->name
;
525 snprintf(bf
, bfsize
, "%#Lx", self
->ip
);
529 static void __callchain__append_graph_browser(struct callchain_node
*self
,
530 newtComponent tree
, u64 total
,
531 int *indexes
, int depth
)
533 struct rb_node
*node
;
534 u64 new_total
, remaining
;
537 if (callchain_param
.mode
== CHAIN_GRAPH_REL
)
538 new_total
= self
->children_hit
;
542 remaining
= new_total
;
543 node
= rb_first(&self
->rb_root
);
545 struct callchain_node
*child
= rb_entry(node
, struct callchain_node
, rb_node
);
546 struct rb_node
*next
= rb_next(node
);
547 u64 cumul
= cumul_hits(child
);
548 struct callchain_list
*chain
;
549 int first
= true, printed
= 0;
553 indexes
[depth
] = NEWT_ARG_APPEND
;
554 indexes
[depth
+ 1] = NEWT_ARG_LAST
;
556 list_for_each_entry(chain
, &child
->val
, list
) {
557 char ipstr
[BITS_PER_LONG
/ 4 + 1],
559 const char *str
= callchain_list__sym_name(chain
, ipstr
, sizeof(ipstr
));
562 double percent
= cumul
* 100.0 / new_total
;
565 if (asprintf(&alloc_str
, "%2.2f%% %s", percent
, str
) < 0)
566 str
= "Not enough memory!";
570 indexes
[depth
] = idx
;
571 indexes
[depth
+ 1] = NEWT_ARG_APPEND
;
572 indexes
[depth
+ 2] = NEWT_ARG_LAST
;
575 newt_checkbox_tree__add(tree
, str
, &chain
->ms
, indexes
);
580 indexes
[depth
] = idx
;
582 indexes
[depth
+ 1] = chain_idx
;
585 __callchain__append_graph_browser(child
, tree
, new_total
, indexes
,
586 depth
+ (chain_idx
!= -1 ? 2 : 1));
591 static void callchain__append_graph_browser(struct callchain_node
*self
,
592 newtComponent tree
, u64 total
,
593 int *indexes
, int parent_idx
)
595 struct callchain_list
*chain
;
598 indexes
[1] = NEWT_ARG_APPEND
;
599 indexes
[2] = NEWT_ARG_LAST
;
601 list_for_each_entry(chain
, &self
->val
, list
) {
602 char ipstr
[BITS_PER_LONG
/ 4 + 1], *str
;
604 if (chain
->ip
>= PERF_CONTEXT_MAX
)
607 if (!i
++ && sort__first_dimension
== SORT_SYM
)
610 str
= callchain_list__sym_name(chain
, ipstr
, sizeof(ipstr
));
611 newt_checkbox_tree__add(tree
, str
, &chain
->ms
, indexes
);
614 indexes
[1] = parent_idx
;
615 indexes
[2] = NEWT_ARG_APPEND
;
616 indexes
[3] = NEWT_ARG_LAST
;
617 __callchain__append_graph_browser(self
, tree
, total
, indexes
, 2);
620 static void hist_entry__append_callchain_browser(struct hist_entry
*self
,
621 newtComponent tree
, u64 total
, int parent_idx
)
623 struct rb_node
*rb_node
;
624 int indexes
[1024] = { [0] = parent_idx
, };
626 struct callchain_node
*chain
;
628 rb_node
= rb_first(&self
->sorted_chain
);
630 chain
= rb_entry(rb_node
, struct callchain_node
, rb_node
);
631 switch (callchain_param
.mode
) {
634 case CHAIN_GRAPH_ABS
: /* falldown */
635 case CHAIN_GRAPH_REL
:
636 callchain__append_graph_browser(chain
, tree
, total
, indexes
, idx
++);
642 rb_node
= rb_next(rb_node
);
646 static size_t hist_entry__append_browser(struct hist_entry
*self
,
647 newtComponent tree
, u64 total
)
652 if (symbol_conf
.exclude_other
&& !self
->parent
)
655 ret
= hist_entry__snprintf(self
, s
, sizeof(s
), NULL
,
656 false, 0, false, total
);
657 if (symbol_conf
.use_callchain
) {
660 indexes
[0] = NEWT_ARG_APPEND
;
661 indexes
[1] = NEWT_ARG_LAST
;
662 newt_checkbox_tree__add(tree
, s
, &self
->ms
, indexes
);
664 newtListboxAppendEntry(tree
, s
, &self
->ms
);
669 static void hist_entry__annotate_browser(struct hist_entry
*self
)
671 struct ui_browser browser
;
672 struct newtExitStruct es
;
673 struct objdump_line
*pos
, *n
;
676 if (self
->ms
.sym
== NULL
)
679 if (hist_entry__annotate(self
, &head
) < 0)
682 ui_helpline__push("Press <- or ESC to exit");
684 memset(&browser
, 0, sizeof(browser
));
685 browser
.entries
= &head
;
687 list_for_each_entry(pos
, &head
, node
) {
688 size_t line_len
= strlen(pos
->line
);
689 if (browser
.width
< line_len
)
690 browser
.width
= line_len
;
691 ++browser
.nr_entries
;
694 browser
.width
+= 18; /* Percentage */
695 ui_browser__run(&browser
, self
->ms
.sym
->name
, &es
);
696 newtFormDestroy(browser
.form
);
698 list_for_each_entry_safe(pos
, n
, &head
, node
) {
699 list_del(&pos
->node
);
700 objdump_line__free(pos
);
705 static const void *newt__symbol_tree_get_current(newtComponent self
)
707 if (symbol_conf
.use_callchain
)
708 return newtCheckboxTreeGetCurrent(self
);
709 return newtListboxGetCurrent(self
);
712 static void hist_browser__selection(newtComponent self
, void *data
)
714 const struct map_symbol
**symbol_ptr
= data
;
715 *symbol_ptr
= newt__symbol_tree_get_current(self
);
718 struct hist_browser
{
719 newtComponent form
, tree
;
720 const struct map_symbol
*selection
;
723 static struct hist_browser
*hist_browser__new(void)
725 struct hist_browser
*self
= malloc(sizeof(*self
));
733 static void hist_browser__delete(struct hist_browser
*self
)
735 newtFormDestroy(self
->form
);
740 static int hist_browser__populate(struct hist_browser
*self
, struct hists
*hists
,
743 int max_len
= 0, idx
, cols
, rows
;
744 struct ui_progress
*progress
;
747 char seq
[] = ".", unit
;
749 unsigned long nr_events
= hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
];
752 newtFormDestroy(self
->form
);
756 nr_events
= convert_unit(nr_events
, &unit
);
757 snprintf(str
, sizeof(str
), "Events: %lu%c ",
759 newtDrawRootText(0, 0, str
);
761 newtGetScreenSize(NULL
, &rows
);
763 if (symbol_conf
.use_callchain
)
764 self
->tree
= newtCheckboxTreeMulti(0, 0, rows
- 5, seq
,
767 self
->tree
= newtListbox(0, 0, rows
- 5,
769 NEWT_FLAG_RETURNEXIT
));
771 newtComponentAddCallback(self
->tree
, hist_browser__selection
,
774 progress
= ui_progress__new("Adding entries to the browser...",
776 if (progress
== NULL
)
780 for (nd
= rb_first(&hists
->entries
); nd
; nd
= rb_next(nd
)) {
781 struct hist_entry
*h
= rb_entry(nd
, struct hist_entry
, rb_node
);
787 len
= hist_entry__append_browser(h
, self
->tree
, hists
->stats
.total_period
);
790 if (symbol_conf
.use_callchain
)
791 hist_entry__append_callchain_browser(h
, self
->tree
,
792 hists
->stats
.total_period
, idx
++);
795 ui_progress__update(progress
, curr_hist
);
798 ui_progress__delete(progress
);
800 newtGetScreenSize(&cols
, &rows
);
805 if (!symbol_conf
.use_callchain
)
806 newtListboxSetWidth(self
->tree
, max_len
);
808 newtCenteredWindow(max_len
+ (symbol_conf
.use_callchain
? 5 : 0),
810 self
->form
= newt_form__new();
811 if (self
->form
== NULL
)
814 newtFormAddHotKey(self
->form
, 'A');
815 newtFormAddHotKey(self
->form
, 'a');
816 newtFormAddHotKey(self
->form
, 'D');
817 newtFormAddHotKey(self
->form
, 'd');
818 newtFormAddHotKey(self
->form
, 'T');
819 newtFormAddHotKey(self
->form
, 't');
820 newtFormAddHotKey(self
->form
, '?');
821 newtFormAddHotKey(self
->form
, 'H');
822 newtFormAddHotKey(self
->form
, 'h');
823 newtFormAddHotKey(self
->form
, NEWT_KEY_F1
);
824 newtFormAddHotKey(self
->form
, NEWT_KEY_RIGHT
);
825 newtFormAddComponents(self
->form
, self
->tree
, NULL
);
826 self
->selection
= newt__symbol_tree_get_current(self
->tree
);
831 static struct hist_entry
*hist_browser__selected_entry(struct hist_browser
*self
)
835 if (!symbol_conf
.use_callchain
)
838 indexes
= newtCheckboxTreeFindItem(self
->tree
, (void *)self
->selection
);
840 bool is_hist_entry
= indexes
[1] == NEWT_ARG_LAST
;
847 return container_of(self
->selection
, struct hist_entry
, ms
);
850 static struct thread
*hist_browser__selected_thread(struct hist_browser
*self
)
852 struct hist_entry
*he
= hist_browser__selected_entry(self
);
853 return he
? he
->thread
: NULL
;
856 static int hist_browser__title(char *bf
, size_t size
, const char *input_name
,
857 const struct dso
*dso
, const struct thread
*thread
)
862 printed
+= snprintf(bf
+ printed
, size
- printed
,
864 (thread
->comm_set
? thread
->comm
: ""),
867 printed
+= snprintf(bf
+ printed
, size
- printed
,
868 "%sDSO: %s", thread
? " " : "",
870 return printed
?: snprintf(bf
, size
, "Report: %s", input_name
);
873 int hists__browse(struct hists
*self
, const char *helpline
, const char *input_name
)
875 struct hist_browser
*browser
= hist_browser__new();
876 struct pstack
*fstack
= pstack__new(2);
877 const struct thread
*thread_filter
= NULL
;
878 const struct dso
*dso_filter
= NULL
;
879 struct newtExitStruct es
;
886 fstack
= pstack__new(2);
890 ui_helpline__push(helpline
);
892 hist_browser__title(msg
, sizeof(msg
), input_name
,
893 dso_filter
, thread_filter
);
894 if (hist_browser__populate(browser
, self
, msg
) < 0)
898 const struct thread
*thread
;
899 const struct dso
*dso
;
901 int nr_options
= 0, choice
= 0, i
,
902 annotate
= -2, zoom_dso
= -2, zoom_thread
= -2;
904 newtFormRun(browser
->form
, &es
);
906 thread
= hist_browser__selected_thread(browser
);
907 dso
= browser
->selection
->map
? browser
->selection
->map
->dso
: NULL
;
909 if (es
.reason
== NEWT_EXIT_HOTKEY
) {
910 if (es
.u
.key
== NEWT_KEY_F1
)
913 switch (toupper(es
.u
.key
)) {
923 ui__help_window("-> Zoom into DSO/Threads & Annotate current symbol\n"
925 "a Annotate current symbol\n"
926 "h/?/F1 Show this window\n"
927 "d Zoom into current DSO\n"
928 "t Zoom into current Thread\n"
929 "q/CTRL+C Exit browser");
933 if (toupper(es
.u
.key
) == 'Q' ||
934 es
.u
.key
== CTRL('c'))
936 if (es
.u
.key
== NEWT_KEY_ESCAPE
) {
937 if (dialog_yesno("Do you really want to exit?"))
943 if (es
.u
.key
== NEWT_KEY_LEFT
) {
946 if (pstack__empty(fstack
))
948 top
= pstack__pop(fstack
);
949 if (top
== &dso_filter
)
951 if (top
== &thread_filter
)
952 goto zoom_out_thread
;
957 if (browser
->selection
->sym
!= NULL
&&
958 asprintf(&options
[nr_options
], "Annotate %s",
959 browser
->selection
->sym
->name
) > 0)
960 annotate
= nr_options
++;
962 if (thread
!= NULL
&&
963 asprintf(&options
[nr_options
], "Zoom %s %s(%d) thread",
964 (thread_filter
? "out of" : "into"),
965 (thread
->comm_set
? thread
->comm
: ""),
967 zoom_thread
= nr_options
++;
970 asprintf(&options
[nr_options
], "Zoom %s %s DSO",
971 (dso_filter
? "out of" : "into"),
972 (dso
->kernel
? "the Kernel" : dso
->short_name
)) > 0)
973 zoom_dso
= nr_options
++;
975 options
[nr_options
++] = (char *)"Exit";
977 choice
= popup_menu(nr_options
, options
);
979 for (i
= 0; i
< nr_options
- 1; ++i
)
982 if (choice
== nr_options
- 1)
988 if (choice
== annotate
) {
989 struct hist_entry
*he
;
991 if (browser
->selection
->map
->dso
->origin
== DSO__ORIG_KERNEL
) {
992 ui_helpline__puts("No vmlinux file found, can't "
993 "annotate with just a "
998 he
= hist_browser__selected_entry(browser
);
1002 hist_entry__annotate_browser(he
);
1003 } else if (choice
== zoom_dso
) {
1006 pstack__remove(fstack
, &dso_filter
);
1013 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
1014 dso
->kernel
? "the Kernel" : dso
->short_name
);
1016 pstack__push(fstack
, &dso_filter
);
1018 hists__filter_by_dso(self
, dso_filter
);
1019 hist_browser__title(msg
, sizeof(msg
), input_name
,
1020 dso_filter
, thread_filter
);
1021 if (hist_browser__populate(browser
, self
, msg
) < 0)
1023 } else if (choice
== zoom_thread
) {
1025 if (thread_filter
) {
1026 pstack__remove(fstack
, &thread_filter
);
1029 thread_filter
= NULL
;
1031 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1032 thread
->comm_set
? thread
->comm
: "",
1034 thread_filter
= thread
;
1035 pstack__push(fstack
, &thread_filter
);
1037 hists__filter_by_thread(self
, thread_filter
);
1038 hist_browser__title(msg
, sizeof(msg
), input_name
,
1039 dso_filter
, thread_filter
);
1040 if (hist_browser__populate(browser
, self
, msg
) < 0)
1046 pstack__delete(fstack
);
1048 hist_browser__delete(browser
);
1052 static struct newtPercentTreeColors
{
1053 const char *topColorFg
, *topColorBg
;
1054 const char *mediumColorFg
, *mediumColorBg
;
1055 const char *normalColorFg
, *normalColorBg
;
1056 const char *selColorFg
, *selColorBg
;
1057 const char *codeColorFg
, *codeColorBg
;
1058 } defaultPercentTreeColors
= {
1060 "green", "lightgray",
1061 "black", "lightgray",
1062 "lightgray", "magenta",
1063 "blue", "lightgray",
1066 void setup_browser(void)
1068 struct newtPercentTreeColors
*c
= &defaultPercentTreeColors
;
1070 if (!isatty(1) || !use_browser
) {
1078 ui_helpline__puts(" ");
1079 sltt_set_color(HE_COLORSET_TOP
, NULL
, c
->topColorFg
, c
->topColorBg
);
1080 sltt_set_color(HE_COLORSET_MEDIUM
, NULL
, c
->mediumColorFg
, c
->mediumColorBg
);
1081 sltt_set_color(HE_COLORSET_NORMAL
, NULL
, c
->normalColorFg
, c
->normalColorBg
);
1082 sltt_set_color(HE_COLORSET_SELECTED
, NULL
, c
->selColorFg
, c
->selColorBg
);
1083 sltt_set_color(HE_COLORSET_CODE
, NULL
, c
->codeColorFg
, c
->codeColorBg
);
1086 void exit_browser(bool wait_for_ok
)
1088 if (use_browser
> 0) {
1090 char title
[] = "Fatal Error", ok
[] = "Ok";
1091 newtWinMessage(title
, ok
, browser__last_msg
);