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