7081e087b9
These are keys people expect when pressed to exit the current widget, so have associate all of them to this semantic. Suggested-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1268401692-9361-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
210 lines
4.3 KiB
C
210 lines
4.3 KiB
C
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#undef _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <newt.h>
|
|
#include <sys/ttydefaults.h>
|
|
|
|
#include "cache.h"
|
|
#include "hist.h"
|
|
#include "session.h"
|
|
#include "sort.h"
|
|
#include "symbol.h"
|
|
|
|
static void newt_form__set_exit_keys(newtComponent self)
|
|
{
|
|
newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
|
|
newtFormAddHotKey(self, 'Q');
|
|
newtFormAddHotKey(self, 'q');
|
|
newtFormAddHotKey(self, CTRL('c'));
|
|
}
|
|
|
|
static newtComponent newt_form__new(void)
|
|
{
|
|
newtComponent self = newtForm(NULL, NULL, 0);
|
|
if (self)
|
|
newt_form__set_exit_keys(self);
|
|
return self;
|
|
}
|
|
|
|
static size_t hist_entry__append_browser(struct hist_entry *self,
|
|
newtComponent listbox, u64 total)
|
|
{
|
|
char bf[1024];
|
|
size_t len;
|
|
FILE *fp;
|
|
|
|
if (symbol_conf.exclude_other && !self->parent)
|
|
return 0;
|
|
|
|
fp = fmemopen(bf, sizeof(bf), "w");
|
|
if (fp == NULL)
|
|
return 0;
|
|
|
|
len = hist_entry__fprintf(self, NULL, false, 0, fp, total);
|
|
|
|
fclose(fp);
|
|
newtListboxAppendEntry(listbox, bf, self);
|
|
return len;
|
|
}
|
|
|
|
static void hist_entry__annotate_browser(struct hist_entry *self)
|
|
{
|
|
FILE *fp;
|
|
struct winsize ws;
|
|
newtComponent form, listbox;
|
|
struct newtExitStruct es;
|
|
char *str;
|
|
size_t line_len, max_line_len = 0;
|
|
size_t max_usable_width;
|
|
char *line = NULL;
|
|
|
|
if (self->sym == NULL)
|
|
return;
|
|
|
|
if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0)
|
|
return;
|
|
|
|
fp = popen(str, "r");
|
|
if (fp == NULL)
|
|
goto out_free_str;
|
|
|
|
newtPushHelpLine("Press ESC to exit");
|
|
get_term_dimensions(&ws);
|
|
listbox = newtListbox(0, 0, ws.ws_row - 5, NEWT_FLAG_SCROLL);
|
|
|
|
while (!feof(fp)) {
|
|
if (getline(&line, &line_len, fp) < 0 || !line_len)
|
|
break;
|
|
while (line_len != 0 && isspace(line[line_len - 1]))
|
|
line[--line_len] = '\0';
|
|
|
|
if (line_len > max_line_len)
|
|
max_line_len = line_len;
|
|
newtListboxAppendEntry(listbox, line, NULL);
|
|
}
|
|
fclose(fp);
|
|
free(line);
|
|
|
|
max_usable_width = ws.ws_col - 22;
|
|
if (max_line_len > max_usable_width)
|
|
max_line_len = max_usable_width;
|
|
|
|
newtListboxSetWidth(listbox, max_line_len);
|
|
|
|
newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name);
|
|
form = newt_form__new();
|
|
newtFormAddComponents(form, listbox, NULL);
|
|
|
|
newtFormRun(form, &es);
|
|
newtFormDestroy(form);
|
|
newtPopWindow();
|
|
newtPopHelpLine();
|
|
out_free_str:
|
|
free(str);
|
|
}
|
|
|
|
void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
|
|
const char *helpline)
|
|
{
|
|
struct sort_entry *se;
|
|
struct rb_node *nd;
|
|
unsigned int width;
|
|
char *col_width = symbol_conf.col_width_list_str;
|
|
struct winsize ws;
|
|
size_t max_len = 0;
|
|
char str[1024];
|
|
newtComponent form, listbox;
|
|
struct newtExitStruct es;
|
|
|
|
snprintf(str, sizeof(str), "Samples: %Ld", session_total);
|
|
newtDrawRootText(0, 0, str);
|
|
newtPushHelpLine(helpline);
|
|
|
|
get_term_dimensions(&ws);
|
|
|
|
form = newt_form__new();
|
|
|
|
listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL |
|
|
NEWT_FLAG_BORDER |
|
|
NEWT_FLAG_RETURNEXIT));
|
|
|
|
list_for_each_entry(se, &hist_entry__sort_list, list) {
|
|
if (se->elide)
|
|
continue;
|
|
width = strlen(se->header);
|
|
if (se->width) {
|
|
if (symbol_conf.col_width_list_str) {
|
|
if (col_width) {
|
|
*se->width = atoi(col_width);
|
|
col_width = strchr(col_width, ',');
|
|
if (col_width)
|
|
++col_width;
|
|
}
|
|
}
|
|
*se->width = max(*se->width, width);
|
|
}
|
|
}
|
|
|
|
for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
|
|
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
|
|
size_t len = hist_entry__append_browser(h, listbox, session_total);
|
|
if (len > max_len)
|
|
max_len = len;
|
|
}
|
|
|
|
newtListboxSetWidth(listbox, max_len);
|
|
newtFormAddComponents(form, listbox, NULL);
|
|
|
|
while (1) {
|
|
struct hist_entry *selection;
|
|
|
|
newtFormRun(form, &es);
|
|
if (es.reason == NEWT_EXIT_HOTKEY)
|
|
break;
|
|
selection = newtListboxGetCurrent(listbox);
|
|
hist_entry__annotate_browser(selection);
|
|
}
|
|
|
|
newtFormDestroy(form);
|
|
}
|
|
|
|
int browser__show_help(const char *format, va_list ap)
|
|
{
|
|
int ret;
|
|
static int backlog;
|
|
static char msg[1024];
|
|
|
|
ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap);
|
|
backlog += ret;
|
|
|
|
if (msg[backlog - 1] == '\n') {
|
|
newtPopHelpLine();
|
|
newtPushHelpLine(msg);
|
|
newtRefresh();
|
|
backlog = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool use_browser;
|
|
|
|
void setup_browser(void)
|
|
{
|
|
if (!isatty(1))
|
|
return;
|
|
|
|
use_browser = true;
|
|
newtInit();
|
|
newtCls();
|
|
newtPushHelpLine(" ");
|
|
}
|
|
|
|
void exit_browser(void)
|
|
{
|
|
if (use_browser)
|
|
newtFinished();
|
|
}
|