3 #include <linux/compiler.h>
4 #include <linux/list.h>
5 #include <linux/rbtree.h>
7 #include <sys/ttydefaults.h>
14 static int ui_browser__percent_color(double percent, bool current)
17 return HE_COLORSET_SELECTED;
18 if (percent >= MIN_RED)
19 return HE_COLORSET_TOP;
20 if (percent >= MIN_GREEN)
21 return HE_COLORSET_MEDIUM;
22 return HE_COLORSET_NORMAL;
25 void ui_browser__set_color(struct ui_browser *self __used, int color)
27 SLsmg_set_color(color);
30 void ui_browser__set_percent_color(struct ui_browser *self,
31 double percent, bool current)
33 int color = ui_browser__percent_color(percent, current);
34 ui_browser__set_color(self, color);
37 void ui_browser__gotorc(struct ui_browser *self, int y, int x)
39 SLsmg_gotorc(self->y + y, self->x + x);
42 void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
44 struct list_head *head = self->entries;
45 struct list_head *pos;
72 void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
74 struct rb_root *root = self->entries;
102 unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
107 if (self->top == NULL)
108 self->top = rb_first(self->entries);
113 ui_browser__gotorc(self, row, 0);
114 self->write(self, nd, row);
115 if (++row == self->height)
123 bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
125 return self->top_idx + row == self->index;
128 void ui_browser__refresh_dimensions(struct ui_browser *self)
131 newtGetScreenSize(&cols, &rows);
133 self->width = cols - 1;
134 self->height = rows - 2;
139 void ui_browser__reset_index(struct ui_browser *self)
141 self->index = self->top_idx = 0;
142 self->seek(self, 0, SEEK_SET);
145 void ui_browser__add_exit_key(struct ui_browser *self, int key)
147 newtFormAddHotKey(self->form, key);
150 void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
154 while (keys[i] && i < 64) {
155 ui_browser__add_exit_key(self, keys[i]);
160 void __ui_browser__show_title(struct ui_browser *browser, const char *title)
163 ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164 slsmg_write_nstring(title, browser->width);
167 void ui_browser__show_title(struct ui_browser *browser, const char *title)
169 pthread_mutex_lock(&ui__lock);
170 __ui_browser__show_title(browser, title);
171 pthread_mutex_unlock(&ui__lock);
174 int ui_browser__show(struct ui_browser *self, const char *title,
175 const char *helpline, ...)
178 int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
179 NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
180 NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
182 if (self->form != NULL)
183 newtFormDestroy(self->form);
185 ui_browser__refresh_dimensions(self);
186 self->form = newtForm(NULL, NULL, 0);
187 if (self->form == NULL)
190 self->sb = newtVerticalScrollbar(self->width, 1, self->height,
192 HE_COLORSET_SELECTED);
193 if (self->sb == NULL)
196 pthread_mutex_lock(&ui__lock);
197 __ui_browser__show_title(self, title);
199 ui_browser__add_exit_keys(self, keys);
200 newtFormAddComponent(self->form, self->sb);
202 va_start(ap, helpline);
203 ui_helpline__vpush(helpline, ap);
205 pthread_mutex_unlock(&ui__lock);
209 void ui_browser__hide(struct ui_browser *self)
211 pthread_mutex_lock(&ui__lock);
212 newtFormDestroy(self->form);
215 pthread_mutex_unlock(&ui__lock);
218 int ui_browser__refresh(struct ui_browser *self)
222 pthread_mutex_lock(&ui__lock);
223 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
224 row = self->refresh(self);
225 ui_browser__set_color(self, HE_COLORSET_NORMAL);
226 SLsmg_fill_region(self->y + row, self->x,
227 self->height - row, self->width, ' ');
228 pthread_mutex_unlock(&ui__lock);
234 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
235 * forget about any reference to any entry in the underlying data structure,
236 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
237 * after an output_resort and hist decay.
239 void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
241 off_t offset = nr_entries - browser->nr_entries;
243 browser->nr_entries = nr_entries;
246 if (browser->top_idx < (u64)-offset)
247 offset = -browser->top_idx;
249 browser->index += offset;
250 browser->top_idx += offset;
253 browser->seek(browser, browser->top_idx, SEEK_SET);
256 int ui_browser__run(struct ui_browser *self)
258 struct newtExitStruct es;
260 if (ui_browser__refresh(self) < 0)
266 newtFormRun(self->form, &es);
268 if (es.reason != NEWT_EXIT_HOTKEY)
272 if (self->index == self->nr_entries - 1)
275 if (self->index == self->top_idx + self->height) {
277 self->seek(self, +1, SEEK_CUR);
281 if (self->index == 0)
284 if (self->index < self->top_idx) {
286 self->seek(self, -1, SEEK_CUR);
291 if (self->top_idx + self->height > self->nr_entries - 1)
294 offset = self->height;
295 if (self->index + offset > self->nr_entries - 1)
296 offset = self->nr_entries - 1 - self->index;
297 self->index += offset;
298 self->top_idx += offset;
299 self->seek(self, +offset, SEEK_CUR);
302 if (self->top_idx == 0)
305 if (self->top_idx < self->height)
306 offset = self->top_idx;
308 offset = self->height;
310 self->index -= offset;
311 self->top_idx -= offset;
312 self->seek(self, -offset, SEEK_CUR);
315 ui_browser__reset_index(self);
318 offset = self->height - 1;
319 if (offset >= self->nr_entries)
320 offset = self->nr_entries - 1;
322 self->index = self->nr_entries - 1;
323 self->top_idx = self->index - offset;
324 self->seek(self, -offset, SEEK_END);
329 if (ui_browser__refresh(self) < 0)
335 unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
337 struct list_head *pos;
338 struct list_head *head = self->entries;
341 if (self->top == NULL || self->top == self->entries)
342 self->top = head->next;
346 list_for_each_from(pos, head) {
347 ui_browser__gotorc(self, row, 0);
348 self->write(self, pos, row);
349 if (++row == self->height)
356 static struct newtPercentTreeColors {
357 const char *topColorFg, *topColorBg;
358 const char *mediumColorFg, *mediumColorBg;
359 const char *normalColorFg, *normalColorBg;
360 const char *selColorFg, *selColorBg;
361 const char *codeColorFg, *codeColorBg;
362 } defaultPercentTreeColors = {
364 "green", "lightgray",
365 "black", "lightgray",
366 "lightgray", "magenta",
370 void ui_browser__init(void)
372 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
374 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
375 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
376 sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
377 sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
378 sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);