newt.c 4.3 KB

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