aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/newt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/newt.c')
-rw-r--r--tools/perf/util/newt.c501
1 files changed, 370 insertions, 131 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index e283a6e6b6e0..ba6acd04c082 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -2,6 +2,7 @@
2#include <stdio.h> 2#include <stdio.h>
3#undef _GNU_SOURCE 3#undef _GNU_SOURCE
4 4
5#include <slang.h>
5#include <stdlib.h> 6#include <stdlib.h>
6#include <newt.h> 7#include <newt.h>
7#include <sys/ttydefaults.h> 8#include <sys/ttydefaults.h>
@@ -57,6 +58,43 @@ void ui_progress__delete(struct ui_progress *self)
57 free(self); 58 free(self);
58} 59}
59 60
61static void ui_helpline__pop(void)
62{
63 newtPopHelpLine();
64}
65
66static void ui_helpline__push(const char *msg)
67{
68 newtPushHelpLine(msg);
69}
70
71static void ui_helpline__vpush(const char *fmt, va_list ap)
72{
73 char *s;
74
75 if (vasprintf(&s, fmt, ap) < 0)
76 vfprintf(stderr, fmt, ap);
77 else {
78 ui_helpline__push(s);
79 free(s);
80 }
81}
82
83static void ui_helpline__fpush(const char *fmt, ...)
84{
85 va_list ap;
86
87 va_start(ap, fmt);
88 ui_helpline__vpush(fmt, ap);
89 va_end(ap);
90}
91
92static void ui_helpline__puts(const char *msg)
93{
94 ui_helpline__pop();
95 ui_helpline__push(msg);
96}
97
60static char browser__last_msg[1024]; 98static char browser__last_msg[1024];
61 99
62int browser__show_help(const char *format, va_list ap) 100int browser__show_help(const char *format, va_list ap)
@@ -69,8 +107,7 @@ int browser__show_help(const char *format, va_list ap)
69 backlog += ret; 107 backlog += ret;
70 108
71 if (browser__last_msg[backlog - 1] == '\n') { 109 if (browser__last_msg[backlog - 1] == '\n') {
72 newtPopHelpLine(); 110 ui_helpline__puts(browser__last_msg);
73 newtPushHelpLine(browser__last_msg);
74 newtRefresh(); 111 newtRefresh();
75 backlog = 0; 112 backlog = 0;
76 } 113 }
@@ -135,6 +172,254 @@ static bool dialog_yesno(const char *msg)
135 return newtWinChoice(NULL, yes, no, (char *)msg) == 1; 172 return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
136} 173}
137 174
175#define HE_COLORSET_TOP 50
176#define HE_COLORSET_MEDIUM 51
177#define HE_COLORSET_NORMAL 52
178#define HE_COLORSET_SELECTED 53
179#define HE_COLORSET_CODE 54
180
181static int ui_browser__percent_color(double percent, bool current)
182{
183 if (current)
184 return HE_COLORSET_SELECTED;
185 if (percent >= MIN_RED)
186 return HE_COLORSET_TOP;
187 if (percent >= MIN_GREEN)
188 return HE_COLORSET_MEDIUM;
189 return HE_COLORSET_NORMAL;
190}
191
192struct ui_browser {
193 newtComponent form, sb;
194 u64 index, first_visible_entry_idx;
195 void *first_visible_entry, *entries;
196 u16 top, left, width, height;
197 void *priv;
198 u32 nr_entries;
199};
200
201static void ui_browser__refresh_dimensions(struct ui_browser *self)
202{
203 int cols, rows;
204 newtGetScreenSize(&cols, &rows);
205
206 if (self->width > cols - 4)
207 self->width = cols - 4;
208 self->height = rows - 5;
209 if (self->height > self->nr_entries)
210 self->height = self->nr_entries;
211 self->top = (rows - self->height) / 2;
212 self->left = (cols - self->width) / 2;
213}
214
215static void ui_browser__reset_index(struct ui_browser *self)
216{
217 self->index = self->first_visible_entry_idx = 0;
218 self->first_visible_entry = NULL;
219}
220
221static int objdump_line__show(struct objdump_line *self, struct list_head *head,
222 int width, struct hist_entry *he, int len,
223 bool current_entry)
224{
225 if (self->offset != -1) {
226 struct symbol *sym = he->ms.sym;
227 unsigned int hits = 0;
228 double percent = 0.0;
229 int color;
230 struct sym_priv *priv = symbol__priv(sym);
231 struct sym_ext *sym_ext = priv->ext;
232 struct sym_hist *h = priv->hist;
233 s64 offset = self->offset;
234 struct objdump_line *next = objdump__get_next_ip_line(head, self);
235
236 while (offset < (s64)len &&
237 (next == NULL || offset < next->offset)) {
238 if (sym_ext) {
239 percent += sym_ext[offset].percent;
240 } else
241 hits += h->ip[offset];
242
243 ++offset;
244 }
245
246 if (sym_ext == NULL && h->sum)
247 percent = 100.0 * hits / h->sum;
248
249 color = ui_browser__percent_color(percent, current_entry);
250 SLsmg_set_color(color);
251 SLsmg_printf(" %7.2f ", percent);
252 if (!current_entry)
253 SLsmg_set_color(HE_COLORSET_CODE);
254 } else {
255 int color = ui_browser__percent_color(0, current_entry);
256 SLsmg_set_color(color);
257 SLsmg_write_nstring(" ", 9);
258 }
259
260 SLsmg_write_char(':');
261 SLsmg_write_nstring(" ", 8);
262 if (!*self->line)
263 SLsmg_write_nstring(" ", width - 18);
264 else
265 SLsmg_write_nstring(self->line, width - 18);
266
267 return 0;
268}
269
270static int ui_browser__refresh_entries(struct ui_browser *self)
271{
272 struct objdump_line *pos;
273 struct list_head *head = self->entries;
274 struct hist_entry *he = self->priv;
275 int row = 0;
276 int len = he->ms.sym->end - he->ms.sym->start;
277
278 if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries)
279 self->first_visible_entry = head->next;
280
281 pos = list_entry(self->first_visible_entry, struct objdump_line, node);
282
283 list_for_each_entry_from(pos, head, node) {
284 bool current_entry = (self->first_visible_entry_idx + row) == self->index;
285 SLsmg_gotorc(self->top + row, self->left);
286 objdump_line__show(pos, head, self->width,
287 he, len, current_entry);
288 if (++row == self->height)
289 break;
290 }
291
292 SLsmg_set_color(HE_COLORSET_NORMAL);
293 SLsmg_fill_region(self->top + row, self->left,
294 self->height - row, self->width, ' ');
295
296 return 0;
297}
298
299static int ui_browser__run(struct ui_browser *self, const char *title,
300 struct newtExitStruct *es)
301{
302 if (self->form) {
303 newtFormDestroy(self->form);
304 newtPopWindow();
305 }
306
307 ui_browser__refresh_dimensions(self);
308 newtCenteredWindow(self->width + 2, self->height, title);
309 self->form = newt_form__new();
310 if (self->form == NULL)
311 return -1;
312
313 self->sb = newtVerticalScrollbar(self->width + 1, 0, self->height,
314 HE_COLORSET_NORMAL,
315 HE_COLORSET_SELECTED);
316 if (self->sb == NULL)
317 return -1;
318
319 newtFormAddHotKey(self->form, NEWT_KEY_UP);
320 newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
321 newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
322 newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
323 newtFormAddHotKey(self->form, NEWT_KEY_HOME);
324 newtFormAddHotKey(self->form, NEWT_KEY_END);
325
326 if (ui_browser__refresh_entries(self) < 0)
327 return -1;
328 newtFormAddComponent(self->form, self->sb);
329
330 while (1) {
331 unsigned int offset;
332
333 newtFormRun(self->form, es);
334
335 if (es->reason != NEWT_EXIT_HOTKEY)
336 break;
337 switch (es->u.key) {
338 case NEWT_KEY_DOWN:
339 if (self->index == self->nr_entries - 1)
340 break;
341 ++self->index;
342 if (self->index == self->first_visible_entry_idx + self->height) {
343 struct list_head *pos = self->first_visible_entry;
344 ++self->first_visible_entry_idx;
345 self->first_visible_entry = pos->next;
346 }
347 break;
348 case NEWT_KEY_UP:
349 if (self->index == 0)
350 break;
351 --self->index;
352 if (self->index < self->first_visible_entry_idx) {
353 struct list_head *pos = self->first_visible_entry;
354 --self->first_visible_entry_idx;
355 self->first_visible_entry = pos->prev;
356 }
357 break;
358 case NEWT_KEY_PGDN:
359 if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
360 break;
361
362 offset = self->height;
363 if (self->index + offset > self->nr_entries - 1)
364 offset = self->nr_entries - 1 - self->index;
365 self->index += offset;
366 self->first_visible_entry_idx += offset;
367
368 while (offset--) {
369 struct list_head *pos = self->first_visible_entry;
370 self->first_visible_entry = pos->next;
371 }
372
373 break;
374 case NEWT_KEY_PGUP:
375 if (self->first_visible_entry_idx == 0)
376 break;
377
378 if (self->first_visible_entry_idx < self->height)
379 offset = self->first_visible_entry_idx;
380 else
381 offset = self->height;
382
383 self->index -= offset;
384 self->first_visible_entry_idx -= offset;
385
386 while (offset--) {
387 struct list_head *pos = self->first_visible_entry;
388 self->first_visible_entry = pos->prev;
389 }
390 break;
391 case NEWT_KEY_HOME:
392 ui_browser__reset_index(self);
393 break;
394 case NEWT_KEY_END: {
395 struct list_head *head = self->entries;
396 offset = self->height - 1;
397
398 if (offset > self->nr_entries)
399 offset = self->nr_entries;
400
401 self->index = self->first_visible_entry_idx = self->nr_entries - 1 - offset;
402 self->first_visible_entry = head->prev;
403 while (offset-- != 0) {
404 struct list_head *pos = self->first_visible_entry;
405 self->first_visible_entry = pos->prev;
406 }
407 }
408 break;
409 case NEWT_KEY_ESCAPE:
410 case CTRL('c'):
411 case 'Q':
412 case 'q':
413 return 0;
414 default:
415 continue;
416 }
417 if (ui_browser__refresh_entries(self) < 0)
418 return -1;
419 }
420 return 0;
421}
422
138/* 423/*
139 * When debugging newt problems it was useful to be able to "unroll" 424 * When debugging newt problems it was useful to be able to "unroll"
140 * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate 425 * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate
@@ -317,62 +602,40 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
317 return ret; 602 return ret;
318} 603}
319 604
320static void map_symbol__annotate_browser(const struct map_symbol *self, 605static void hist_entry__annotate_browser(struct hist_entry *self)
321 const char *input_name)
322{ 606{
323 FILE *fp; 607 struct ui_browser browser;
324 int cols, rows;
325 newtComponent form, tree;
326 struct newtExitStruct es; 608 struct newtExitStruct es;
327 char *str; 609 struct objdump_line *pos, *n;
328 size_t line_len, max_line_len = 0; 610 LIST_HEAD(head);
329 size_t max_usable_width;
330 char *line = NULL;
331 611
332 if (self->sym == NULL) 612 if (self->ms.sym == NULL)
333 return; 613 return;
334 614
335 if (asprintf(&str, "perf annotate -i \"%s\" -d \"%s\" %s 2>&1 | expand", 615 if (hist_entry__annotate(self, &head) < 0)
336 input_name, self->map->dso->name, self->sym->name) < 0)
337 return; 616 return;
338 617
339 fp = popen(str, "r"); 618 ui_helpline__push("Press ESC to exit");
340 if (fp == NULL)
341 goto out_free_str;
342
343 newtPushHelpLine("Press ESC to exit");
344 newtGetScreenSize(&cols, &rows);
345 tree = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL);
346
347 while (!feof(fp)) {
348 if (getline(&line, &line_len, fp) < 0 || !line_len)
349 break;
350 while (line_len != 0 && isspace(line[line_len - 1]))
351 line[--line_len] = '\0';
352 619
353 if (line_len > max_line_len) 620 memset(&browser, 0, sizeof(browser));
354 max_line_len = line_len; 621 browser.entries = &head;
355 newtListboxAppendEntry(tree, line, NULL); 622 browser.priv = self;
623 list_for_each_entry(pos, &head, node) {
624 size_t line_len = strlen(pos->line);
625 if (browser.width < line_len)
626 browser.width = line_len;
627 ++browser.nr_entries;
356 } 628 }
357 fclose(fp);
358 free(line);
359 629
360 max_usable_width = cols - 22; 630 browser.width += 18; /* Percentage */
361 if (max_line_len > max_usable_width) 631 ui_browser__run(&browser, self->ms.sym->name, &es);
362 max_line_len = max_usable_width; 632 newtFormDestroy(browser.form);
363
364 newtListboxSetWidth(tree, max_line_len);
365
366 newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name);
367 form = newt_form__new();
368 newtFormAddComponent(form, tree);
369
370 newtFormRun(form, &es);
371 newtFormDestroy(form);
372 newtPopWindow(); 633 newtPopWindow();
373 newtPopHelpLine(); 634 list_for_each_entry_safe(pos, n, &head, node) {
374out_free_str: 635 list_del(&pos->node);
375 free(str); 636 objdump_line__free(pos);
637 }
638 ui_helpline__pop();
376} 639}
377 640
378static const void *newt__symbol_tree_get_current(newtComponent self) 641static const void *newt__symbol_tree_get_current(newtComponent self)
@@ -410,8 +673,8 @@ static void hist_browser__delete(struct hist_browser *self)
410 free(self); 673 free(self);
411} 674}
412 675
413static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists, 676static int hist_browser__populate(struct hist_browser *self, struct hists *hists,
414 u64 nr_hists, u64 session_total, const char *title) 677 const char *title)
415{ 678{
416 int max_len = 0, idx, cols, rows; 679 int max_len = 0, idx, cols, rows;
417 struct ui_progress *progress; 680 struct ui_progress *progress;
@@ -426,7 +689,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
426 } 689 }
427 690
428 snprintf(str, sizeof(str), "Samples: %Ld ", 691 snprintf(str, sizeof(str), "Samples: %Ld ",
429 session_total); 692 hists->stats.total);
430 newtDrawRootText(0, 0, str); 693 newtDrawRootText(0, 0, str);
431 694
432 newtGetScreenSize(NULL, &rows); 695 newtGetScreenSize(NULL, &rows);
@@ -442,24 +705,25 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
442 newtComponentAddCallback(self->tree, hist_browser__selection, 705 newtComponentAddCallback(self->tree, hist_browser__selection,
443 &self->selection); 706 &self->selection);
444 707
445 progress = ui_progress__new("Adding entries to the browser...", nr_hists); 708 progress = ui_progress__new("Adding entries to the browser...",
709 hists->nr_entries);
446 if (progress == NULL) 710 if (progress == NULL)
447 return -1; 711 return -1;
448 712
449 idx = 0; 713 idx = 0;
450 for (nd = rb_first(hists); nd; nd = rb_next(nd)) { 714 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
451 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 715 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
452 int len; 716 int len;
453 717
454 if (h->filtered) 718 if (h->filtered)
455 continue; 719 continue;
456 720
457 len = hist_entry__append_browser(h, self->tree, session_total); 721 len = hist_entry__append_browser(h, self->tree, hists->stats.total);
458 if (len > max_len) 722 if (len > max_len)
459 max_len = len; 723 max_len = len;
460 if (symbol_conf.use_callchain) 724 if (symbol_conf.use_callchain)
461 hist_entry__append_callchain_browser(h, self->tree, 725 hist_entry__append_callchain_browser(h, self->tree,
462 session_total, idx++); 726 hists->stats.total, idx++);
463 ++curr_hist; 727 ++curr_hist;
464 if (curr_hist % 5) 728 if (curr_hist % 5)
465 ui_progress__update(progress, curr_hist); 729 ui_progress__update(progress, curr_hist);
@@ -490,58 +754,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
490 return 0; 754 return 0;
491} 755}
492 756
493enum hist_filter { 757static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self)
494 HIST_FILTER__DSO,
495 HIST_FILTER__THREAD,
496};
497
498static u64 hists__filter_by_dso(struct rb_root *hists, const struct dso *dso,
499 u64 *session_total)
500{
501 struct rb_node *nd;
502 u64 nr_hists = 0;
503
504 *session_total = 0;
505
506 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
507 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
508
509 if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) {
510 h->filtered |= (1 << HIST_FILTER__DSO);
511 continue;
512 }
513 h->filtered &= ~(1 << HIST_FILTER__DSO);
514 ++nr_hists;
515 *session_total += h->count;
516 }
517
518 return nr_hists;
519}
520
521static u64 hists__filter_by_thread(struct rb_root *hists, const struct thread *thread,
522 u64 *session_total)
523{
524 struct rb_node *nd;
525 u64 nr_hists = 0;
526
527 *session_total = 0;
528
529 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
530 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
531
532 if (thread != NULL && h->thread != thread) {
533 h->filtered |= (1 << HIST_FILTER__THREAD);
534 continue;
535 }
536 h->filtered &= ~(1 << HIST_FILTER__THREAD);
537 ++nr_hists;
538 *session_total += h->count;
539 }
540
541 return nr_hists;
542}
543
544static struct thread *hist_browser__selected_thread(struct hist_browser *self)
545{ 758{
546 int *indexes; 759 int *indexes;
547 760
@@ -557,7 +770,13 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
557 } 770 }
558 return NULL; 771 return NULL;
559out: 772out:
560 return *(struct thread **)(self->selection + 1); 773 return container_of(self->selection, struct hist_entry, ms);
774}
775
776static struct thread *hist_browser__selected_thread(struct hist_browser *self)
777{
778 struct hist_entry *he = hist_browser__selected_entry(self);
779 return he ? he->thread : NULL;
561} 780}
562 781
563static int hist_browser__title(char *bf, size_t size, const char *input_name, 782static int hist_browser__title(char *bf, size_t size, const char *input_name,
@@ -577,9 +796,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
577 return printed ?: snprintf(bf, size, "Report: %s", input_name); 796 return printed ?: snprintf(bf, size, "Report: %s", input_name);
578} 797}
579 798
580int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, 799int hists__browse(struct hists *self, const char *helpline, const char *input_name)
581 u64 session_total, const char *helpline,
582 const char *input_name)
583{ 800{
584 struct hist_browser *browser = hist_browser__new(); 801 struct hist_browser *browser = hist_browser__new();
585 const struct thread *thread_filter = NULL; 802 const struct thread *thread_filter = NULL;
@@ -591,11 +808,11 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
591 if (browser == NULL) 808 if (browser == NULL)
592 return -1; 809 return -1;
593 810
594 newtPushHelpLine(helpline); 811 ui_helpline__push(helpline);
595 812
596 hist_browser__title(msg, sizeof(msg), input_name, 813 hist_browser__title(msg, sizeof(msg), input_name,
597 dso_filter, thread_filter); 814 dso_filter, thread_filter);
598 if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) 815 if (hist_browser__populate(browser, self, msg) < 0)
599 goto out; 816 goto out;
600 817
601 while (1) { 818 while (1) {
@@ -653,46 +870,48 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
653 continue; 870 continue;
654do_annotate: 871do_annotate:
655 if (choice == annotate) { 872 if (choice == annotate) {
873 struct hist_entry *he;
874
656 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { 875 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
657 newtPopHelpLine(); 876 ui_helpline__puts("No vmlinux file found, can't "
658 newtPushHelpLine("No vmlinux file found, can't "
659 "annotate with just a " 877 "annotate with just a "
660 "kallsyms file"); 878 "kallsyms file");
661 continue; 879 continue;
662 } 880 }
663 map_symbol__annotate_browser(browser->selection, input_name); 881
882 he = hist_browser__selected_entry(browser);
883 if (he == NULL)
884 continue;
885
886 hist_entry__annotate_browser(he);
664 } else if (choice == zoom_dso) { 887 } else if (choice == zoom_dso) {
665 if (dso_filter) { 888 if (dso_filter) {
666 newtPopHelpLine(); 889 ui_helpline__pop();
667 dso_filter = NULL; 890 dso_filter = NULL;
668 } else { 891 } else {
669 snprintf(msg, sizeof(msg), 892 ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"",
670 "To zoom out press -> + \"Zoom out of %s DSO\"", 893 dso->kernel ? "the Kernel" : dso->short_name);
671 dso->kernel ? "the Kernel" : dso->short_name);
672 newtPushHelpLine(msg);
673 dso_filter = dso; 894 dso_filter = dso;
674 } 895 }
675 nr_hists = hists__filter_by_dso(hists, dso_filter, &session_total); 896 hists__filter_by_dso(self, dso_filter);
676 hist_browser__title(msg, sizeof(msg), input_name, 897 hist_browser__title(msg, sizeof(msg), input_name,
677 dso_filter, thread_filter); 898 dso_filter, thread_filter);
678 if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) 899 if (hist_browser__populate(browser, self, msg) < 0)
679 goto out; 900 goto out;
680 } else if (choice == zoom_thread) { 901 } else if (choice == zoom_thread) {
681 if (thread_filter) { 902 if (thread_filter) {
682 newtPopHelpLine(); 903 ui_helpline__pop();
683 thread_filter = NULL; 904 thread_filter = NULL;
684 } else { 905 } else {
685 snprintf(msg, sizeof(msg), 906 ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"",
686 "To zoom out press -> + \"Zoom out of %s(%d) thread\"", 907 thread->comm_set ? thread->comm : "",
687 (thread->comm_set ? thread->comm : ""), 908 thread->pid);
688 thread->pid);
689 newtPushHelpLine(msg);
690 thread_filter = thread; 909 thread_filter = thread;
691 } 910 }
692 nr_hists = hists__filter_by_thread(hists, thread_filter, &session_total); 911 hists__filter_by_thread(self, thread_filter);
693 hist_browser__title(msg, sizeof(msg), input_name, 912 hist_browser__title(msg, sizeof(msg), input_name,
694 dso_filter, thread_filter); 913 dso_filter, thread_filter);
695 if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) 914 if (hist_browser__populate(browser, self, msg) < 0)
696 goto out; 915 goto out;
697 } 916 }
698 } 917 }
@@ -702,15 +921,35 @@ out:
702 return err; 921 return err;
703} 922}
704 923
924static struct newtPercentTreeColors {
925 const char *topColorFg, *topColorBg;
926 const char *mediumColorFg, *mediumColorBg;
927 const char *normalColorFg, *normalColorBg;
928 const char *selColorFg, *selColorBg;
929 const char *codeColorFg, *codeColorBg;
930} defaultPercentTreeColors = {
931 "red", "lightgray",
932 "green", "lightgray",
933 "black", "lightgray",
934 "lightgray", "magenta",
935 "blue", "lightgray",
936};
937
705void setup_browser(void) 938void setup_browser(void)
706{ 939{
940 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
707 if (!isatty(1)) 941 if (!isatty(1))
708 return; 942 return;
709 943
710 use_browser = true; 944 use_browser = true;
711 newtInit(); 945 newtInit();
712 newtCls(); 946 newtCls();
713 newtPushHelpLine(" "); 947 ui_helpline__puts(" ");
948 SLtt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
949 SLtt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
950 SLtt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
951 SLtt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
952 SLtt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
714} 953}
715 954
716void exit_browser(bool wait_for_ok) 955void exit_browser(bool wait_for_ok)