perf tools: Exit browser before printing usage when unkown option passed
[linux-2.6-block.git] / tools / perf / util / newt.c
CommitLineData
f9224c5c
ACM
1#define _GNU_SOURCE
2#include <stdio.h>
3#undef _GNU_SOURCE
4
5#include <stdlib.h>
6#include <newt.h>
7081e087 7#include <sys/ttydefaults.h>
f9224c5c
ACM
8
9#include "cache.h"
10#include "hist.h"
11#include "session.h"
12#include "sort.h"
13#include "symbol.h"
14
7081e087
ACM
15static void newt_form__set_exit_keys(newtComponent self)
16{
17 newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
18 newtFormAddHotKey(self, 'Q');
19 newtFormAddHotKey(self, 'q');
20 newtFormAddHotKey(self, CTRL('c'));
21}
22
23static newtComponent newt_form__new(void)
24{
25 newtComponent self = newtForm(NULL, NULL, 0);
26 if (self)
27 newt_form__set_exit_keys(self);
28 return self;
29}
30
f9224c5c
ACM
31static size_t hist_entry__append_browser(struct hist_entry *self,
32 newtComponent listbox, u64 total)
33{
34 char bf[1024];
35 size_t len;
36 FILE *fp;
37
38 if (symbol_conf.exclude_other && !self->parent)
39 return 0;
40
41 fp = fmemopen(bf, sizeof(bf), "w");
42 if (fp == NULL)
43 return 0;
44
45 len = hist_entry__fprintf(self, NULL, false, 0, fp, total);
46
47 fclose(fp);
48 newtListboxAppendEntry(listbox, bf, self);
49 return len;
50}
51
52static void hist_entry__annotate_browser(struct hist_entry *self)
53{
54 FILE *fp;
cb7afb70 55 int cols, rows;
f9224c5c
ACM
56 newtComponent form, listbox;
57 struct newtExitStruct es;
58 char *str;
59 size_t line_len, max_line_len = 0;
60 size_t max_usable_width;
61 char *line = NULL;
62
63 if (self->sym == NULL)
64 return;
65
d06d92b7 66 if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->sym->name) < 0)
f9224c5c
ACM
67 return;
68
69 fp = popen(str, "r");
70 if (fp == NULL)
71 goto out_free_str;
72
73 newtPushHelpLine("Press ESC to exit");
cb7afb70
ACM
74 newtGetScreenSize(&cols, &rows);
75 listbox = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL);
f9224c5c
ACM
76
77 while (!feof(fp)) {
78 if (getline(&line, &line_len, fp) < 0 || !line_len)
79 break;
80 while (line_len != 0 && isspace(line[line_len - 1]))
81 line[--line_len] = '\0';
82
83 if (line_len > max_line_len)
84 max_line_len = line_len;
85 newtListboxAppendEntry(listbox, line, NULL);
86 }
87 fclose(fp);
88 free(line);
89
cb7afb70 90 max_usable_width = cols - 22;
f9224c5c
ACM
91 if (max_line_len > max_usable_width)
92 max_line_len = max_usable_width;
93
94 newtListboxSetWidth(listbox, max_line_len);
95
cb7afb70 96 newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name);
7081e087 97 form = newt_form__new();
f9224c5c
ACM
98 newtFormAddComponents(form, listbox, NULL);
99
100 newtFormRun(form, &es);
101 newtFormDestroy(form);
102 newtPopWindow();
103 newtPopHelpLine();
104out_free_str:
105 free(str);
106}
107
108void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
109 const char *helpline)
110{
111 struct sort_entry *se;
112 struct rb_node *nd;
113 unsigned int width;
114 char *col_width = symbol_conf.col_width_list_str;
cb7afb70 115 int rows;
f9224c5c
ACM
116 size_t max_len = 0;
117 char str[1024];
118 newtComponent form, listbox;
119 struct newtExitStruct es;
120
121 snprintf(str, sizeof(str), "Samples: %Ld", session_total);
122 newtDrawRootText(0, 0, str);
123 newtPushHelpLine(helpline);
124
cb7afb70 125 newtGetScreenSize(NULL, &rows);
f9224c5c 126
7081e087 127 form = newt_form__new();
f9224c5c 128
cb7afb70
ACM
129 listbox = newtListbox(1, 1, rows - 2, (NEWT_FLAG_SCROLL |
130 NEWT_FLAG_BORDER |
131 NEWT_FLAG_RETURNEXIT));
f9224c5c
ACM
132
133 list_for_each_entry(se, &hist_entry__sort_list, list) {
134 if (se->elide)
135 continue;
136 width = strlen(se->header);
137 if (se->width) {
138 if (symbol_conf.col_width_list_str) {
139 if (col_width) {
140 *se->width = atoi(col_width);
141 col_width = strchr(col_width, ',');
142 if (col_width)
143 ++col_width;
144 }
145 }
146 *se->width = max(*se->width, width);
147 }
148 }
149
150 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
151 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
152 size_t len = hist_entry__append_browser(h, listbox, session_total);
153 if (len > max_len)
154 max_len = len;
155 }
156
157 newtListboxSetWidth(listbox, max_len);
158 newtFormAddComponents(form, listbox, NULL);
159
160 while (1) {
161 struct hist_entry *selection;
162
163 newtFormRun(form, &es);
164 if (es.reason == NEWT_EXIT_HOTKEY)
165 break;
166 selection = newtListboxGetCurrent(listbox);
167 hist_entry__annotate_browser(selection);
168 }
169
170 newtFormDestroy(form);
171}
172
f3a1f0ea
ACM
173static char browser__last_msg[1024];
174
f9224c5c
ACM
175int browser__show_help(const char *format, va_list ap)
176{
177 int ret;
178 static int backlog;
f9224c5c 179
f3a1f0ea
ACM
180 ret = vsnprintf(browser__last_msg + backlog,
181 sizeof(browser__last_msg) - backlog, format, ap);
f9224c5c
ACM
182 backlog += ret;
183
f3a1f0ea 184 if (browser__last_msg[backlog - 1] == '\n') {
f9224c5c 185 newtPopHelpLine();
f3a1f0ea 186 newtPushHelpLine(browser__last_msg);
f9224c5c
ACM
187 newtRefresh();
188 backlog = 0;
189 }
190
191 return ret;
192}
193
f9224c5c
ACM
194void setup_browser(void)
195{
196 if (!isatty(1))
197 return;
198
199 use_browser = true;
200 newtInit();
201 newtCls();
202 newtPushHelpLine(" ");
203}
204
f3a1f0ea 205void exit_browser(bool wait_for_ok)
f9224c5c 206{
f3a1f0ea
ACM
207 if (use_browser) {
208 if (wait_for_ok) {
209 char title[] = "Fatal Error", ok[] = "Ok";
210 newtWinMessage(title, ok, browser__last_msg);
211 }
f9224c5c 212 newtFinished();
f3a1f0ea 213 }
f9224c5c 214}