1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../util.h"
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../cache.h"
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../perf.h"
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "libslang.h"
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "ui.h"
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util.h"
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/compiler.h>
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/list.h>
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/rbtree.h>
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/ttydefaults.h>
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "browser.h"
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "helpline.h"
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "keysyms.h"
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../color.h"
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int ui_browser__percent_color(struct ui_browser *browser,
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     double percent, bool current)
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (current && (!browser->use_navkeypressed || browser->navkeypressed))
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return HE_COLORSET_SELECTED;
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (percent >= MIN_RED)
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return HE_COLORSET_TOP;
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (percent >= MIN_GREEN)
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return HE_COLORSET_MEDIUM;
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return HE_COLORSET_NORMAL;
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__set_color(struct ui_browser *browser, int color)
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = browser->current_color;
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->current_color = color;
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_color(color);
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__set_percent_color(struct ui_browser *browser,
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				   double percent, bool current)
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 int color = ui_browser__percent_color(browser, percent, current);
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 ui_browser__set_color(browser, color);
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__gotorc(struct ui_browser *browser, int y, int x)
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_gotorc(browser->y + y, browser->x + x);
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct list_head *
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengui_browser__list_head_filter_entries(struct ui_browser *browser,
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				     struct list_head *pos)
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	do {
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!browser->filter || !browser->filter(browser, pos))
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return pos;
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pos = pos->next;
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} while (pos != browser->entries);
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct list_head *
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  struct list_head *pos)
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	do {
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!browser->filter || !browser->filter(browser, pos))
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return pos;
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pos = pos->prev;
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} while (pos != browser->entries);
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence)
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct list_head *head = browser->entries;
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct list_head *pos;
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (browser->nr_entries == 0)
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (whence) {
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_SET:
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pos = ui_browser__list_head_filter_entries(browser, head->next);
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_CUR:
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pos = browser->top;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_END:
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pos = ui_browser__list_head_filter_prev_entries(browser, head->prev);
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	assert(pos != NULL);
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (offset > 0) {
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (offset-- != 0)
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pos = ui_browser__list_head_filter_entries(browser, pos->next);
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else {
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (offset++ != 0)
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pos = ui_browser__list_head_filter_prev_entries(browser, pos->prev);
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->top = pos;
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence)
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *root = browser->entries;
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (whence) {
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_SET:
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		nd = rb_first(root);
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_CUR:
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		nd = browser->top;
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_END:
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		nd = rb_last(root);
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (offset > 0) {
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (offset-- != 0)
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			nd = rb_next(nd);
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else {
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (offset++ != 0)
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			nd = rb_prev(nd);
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->top = nd;
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengunsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser)
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *nd;
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int row = 0;
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (browser->top == NULL)
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                browser->top = rb_first(browser->entries);
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	nd = browser->top;
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (nd != NULL) {
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, row, 0);
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->write(browser, nd, row);
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (++row == browser->height)
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		nd = rb_next(nd);
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return row;
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row)
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return browser->top_idx + row == browser->index;
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__refresh_dimensions(struct ui_browser *browser)
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->width = SLtt_Screen_Cols - 1;
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->height = SLtt_Screen_Rows - 2;
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->y = 1;
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->x = 0;
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__handle_resize(struct ui_browser *browser)
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui__refresh_dimensions(false);
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__show(browser, browser->title, ui_helpline__current);
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__refresh(browser);
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__warning(struct ui_browser *browser, int timeout,
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			const char *format, ...)
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_list args;
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *text;
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int key = 0, err;
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_start(args, format);
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	err = vasprintf(&text, format, args);
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_end(args);
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (err < 0) {
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		va_start(args, format);
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_helpline__vpush(format, args);
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		va_end(args);
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else {
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while ((key == ui__question_window("Warning!", text,
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						   "Press any key...",
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						   timeout)) == K_RESIZE)
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_browser__handle_resize(browser);
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		free(text);
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return key;
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__help_window(struct ui_browser *browser, const char *text)
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int key;
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while ((key = ui__help_window(text)) == K_RESIZE)
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__handle_resize(browser);
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return key;
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text)
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int key;
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while ((key = ui__dialog_yesno(text)) == K_RESIZE)
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__handle_resize(browser);
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return key == K_ENTER || toupper(key) == 'Y';
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__reset_index(struct ui_browser *browser)
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->index = browser->top_idx = 0;
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->seek(browser, 0, SEEK_SET);
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid __ui_browser__show_title(struct ui_browser *browser, const char *title)
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_gotorc(0, 0);
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__set_color(browser, HE_COLORSET_ROOT);
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	slsmg_write_nstring(title, browser->width + 1);
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__show_title(struct ui_browser *browser, const char *title)
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_lock(&ui__lock);
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	__ui_browser__show_title(browser, title);
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_unlock(&ui__lock);
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__show(struct ui_browser *browser, const char *title,
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     const char *helpline, ...)
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int err;
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_list ap;
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__refresh_dimensions(browser);
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_lock(&ui__lock);
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	__ui_browser__show_title(browser, title);
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->title = title;
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(browser->helpline);
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->helpline = NULL;
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_start(ap, helpline);
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	err = vasprintf(&browser->helpline, helpline, ap);
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	va_end(ap);
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (err > 0)
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_helpline__push(browser->helpline);
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_unlock(&ui__lock);
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return err ? 0 : -1;
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__hide(struct ui_browser *browser __maybe_unused)
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_lock(&ui__lock);
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_helpline__pop();
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(browser->helpline);
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->helpline = NULL;
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_unlock(&ui__lock);
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void ui_browser__scrollbar_set(struct ui_browser *browser)
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int height = browser->height, h = 0, pct = 0,
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	    col = browser->width,
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	    row = browser->y - 1;
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (browser->nr_entries > 1) {
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pct = ((browser->index * (browser->height - 1)) /
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       (browser->nr_entries - 1));
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(1);
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (h < height) {
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	        ui_browser__gotorc(browser, row++, col);
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_CKBRD_CHAR);
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		++h;
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(0);
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int __ui_browser__refresh(struct ui_browser *browser)
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int row;
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int width = browser->width;
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	row = browser->refresh(browser);
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__set_color(browser, HE_COLORSET_NORMAL);
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!browser->use_navkeypressed || browser->navkeypressed)
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__scrollbar_set(browser);
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		width += 1;
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_fill_region(browser->y + row, browser->x,
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			  browser->height - row, width, ' ');
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__refresh(struct ui_browser *browser)
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_lock(&ui__lock);
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	__ui_browser__refresh(browser);
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pthread_mutex_unlock(&ui__lock);
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Here we're updating nr_entries _after_ we started browsing, i.e.  we have to
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * forget about any reference to any entry in the underlying data structure,
333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * after an output_resort and hist decay.
335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	off_t offset = nr_entries - browser->nr_entries;
339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->nr_entries = nr_entries;
341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (offset < 0) {
343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (browser->top_idx < (u64)-offset)
344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			offset = -browser->top_idx;
345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->index += offset;
347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->top_idx += offset;
348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->top = NULL;
351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	browser->seek(browser, browser->top_idx, SEEK_SET);
352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint ui_browser__run(struct ui_browser *browser, int delay_secs)
355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int err, key;
357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (1) {
359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		off_t offset;
360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pthread_mutex_lock(&ui__lock);
362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = __ui_browser__refresh(browser);
363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_refresh();
364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pthread_mutex_unlock(&ui__lock);
365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (err < 0)
366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		key = ui__getch(delay_secs);
369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (key == K_RESIZE) {
371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui__refresh_dimensions(false);
372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_browser__refresh_dimensions(browser);
373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			__ui_browser__show_title(browser, browser->title);
374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_helpline__puts(browser->helpline);
375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (browser->use_navkeypressed && !browser->navkeypressed) {
379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (key == K_DOWN || key == K_UP ||
380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    key == K_PGDN || key == K_PGUP ||
381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    key == K_HOME || key == K_END ||
382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    key == ' ') {
383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				browser->navkeypressed = true;
384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			} else
386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return key;
387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		switch (key) {
390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_DOWN:
391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->index == browser->nr_entries - 1)
392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			++browser->index;
394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->index == browser->top_idx + browser->height) {
395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				++browser->top_idx;
396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				browser->seek(browser, +1, SEEK_CUR);
397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_UP:
400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->index == 0)
401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			--browser->index;
403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->index < browser->top_idx) {
404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				--browser->top_idx;
405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				browser->seek(browser, -1, SEEK_CUR);
406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_PGDN:
409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case ' ':
410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->top_idx + browser->height > browser->nr_entries - 1)
411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			offset = browser->height;
414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->index + offset > browser->nr_entries - 1)
415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				offset = browser->nr_entries - 1 - browser->index;
416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->index += offset;
417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->top_idx += offset;
418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->seek(browser, +offset, SEEK_CUR);
419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_PGUP:
421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->top_idx == 0)
422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (browser->top_idx < browser->height)
425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				offset = browser->top_idx;
426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			else
427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				offset = browser->height;
428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->index -= offset;
430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->top_idx -= offset;
431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->seek(browser, -offset, SEEK_CUR);
432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_HOME:
434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_browser__reset_index(browser);
435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case K_END:
437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			offset = browser->height - 1;
438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (offset >= browser->nr_entries)
439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				offset = browser->nr_entries - 1;
440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->index = browser->nr_entries - 1;
442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->top_idx = browser->index - offset;
443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->seek(browser, -offset, SEEK_END);
444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		default:
446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return key;
447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengunsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct list_head *pos;
455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct list_head *head = browser->entries;
456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int row = 0;
457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (browser->top == NULL || browser->top == browser->entries)
459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                browser->top = ui_browser__list_head_filter_entries(browser, head->next);
460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pos = browser->top;
462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_from(pos, head) {
464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!browser->filter || !browser->filter(browser, pos)) {
465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_browser__gotorc(browser, row, 0);
466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->write(browser, pos, row);
467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (++row == browser->height)
468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return row;
473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct ui_browser_colorset {
476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *name, *fg, *bg;
477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int colorset;
478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} ui_browser__colorsets[] = {
479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_TOP,
481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "top",
482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "red",
483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "default",
484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_MEDIUM,
487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "medium",
488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "green",
489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "default",
490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_NORMAL,
493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "normal",
494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "default",
495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "default",
496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_SELECTED,
499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "selected",
500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "black",
501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "lightgray",
502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_CODE,
505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "code",
506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "blue",
507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "default",
508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_ADDR,
511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "addr",
512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "magenta",
513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "default",
514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.colorset = HE_COLORSET_ROOT,
517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name	  = "root",
518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.fg	  = "white",
519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.bg	  = "blue",
520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name = NULL,
523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int ui_browser__color_config(const char *var, const char *value,
528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				    void *data __maybe_unused)
529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *fg = NULL, *bg;
531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* same dir for all commands */
534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (prefixcmp(var, "colors.") != 0)
535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const char *name = var + 7;
539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (strcmp(ui_browser__colorsets[i].name, name) != 0)
541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fg = strdup(value);
544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fg == NULL)
545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		bg = strchr(fg, ',');
548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (bg == NULL)
549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		*bg = '\0';
552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while (isspace(*++bg));
553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__colorsets[i].bg = bg;
554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__colorsets[i].fg = fg;
555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(fg);
559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence)
563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (whence) {
565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_SET:
566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->top = browser->entries;
567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_CUR:
569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->top = browser->top + browser->top_idx + offset;
570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case SEEK_END:
572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->top = browser->top + browser->nr_entries + offset;
573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengunsigned int ui_browser__argv_refresh(struct ui_browser *browser)
580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned int row = 0, idx = browser->top_idx;
582e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char **pos;
583e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
584e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (browser->top == NULL)
585e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		browser->top = browser->entries;
586e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
587e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pos = (char **)browser->top;
588e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (idx < browser->nr_entries) {
589e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!browser->filter || !browser->filter(browser, *pos)) {
590e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ui_browser__gotorc(browser, row, 0);
591e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			browser->write(browser, pos, row);
592e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (++row == browser->height)
593e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
594e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
595e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
596e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		++idx;
597e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		++pos;
598e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
599e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
600e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return row;
601e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
602e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
603e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid __ui_browser__vline(struct ui_browser *browser, unsigned int column,
604e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 u16 start, u16 end)
605e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
606e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(1);
607e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__gotorc(browser, start, column);
608e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_draw_vline(end - start + 1);
609e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(0);
610e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
611e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
612e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__write_graph(struct ui_browser *browser __maybe_unused,
613e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			     int graph)
614e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
615e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(1);
616e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_write_char(graph);
617e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(0);
618e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
619e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
620e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void __ui_browser__line_arrow_up(struct ui_browser *browser,
621e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					unsigned int column,
622e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					u64 start, u64 end)
623e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
624e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned int row, end_row;
625e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
626e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(1);
627e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
628e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (start < browser->top_idx + browser->height) {
629e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		row = start - browser->top_idx;
630e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, row, column);
631e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_LLCORN_CHAR);
632e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, row, column + 1);
633e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_draw_hline(2);
634e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
635e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (row-- == 0)
636e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
637e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else
638e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		row = browser->height - 1;
639e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
640e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (end > browser->top_idx)
641e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		end_row = end - browser->top_idx;
642e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
643e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		end_row = 0;
644e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
645e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__gotorc(browser, end_row, column);
646e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_draw_vline(row - end_row + 1);
647e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
648e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__gotorc(browser, end_row, column);
649e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (end >= browser->top_idx) {
650e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_ULCORN_CHAR);
651e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, end_row, column + 1);
652e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_HLINE_CHAR);
653e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, end_row, column + 2);
654e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_RARROW_CHAR);
655e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
656e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout:
657e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(0);
658e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
659e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
660e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void __ui_browser__line_arrow_down(struct ui_browser *browser,
661e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  unsigned int column,
662e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  u64 start, u64 end)
663e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
664e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned int row, end_row;
665e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
666e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(1);
667e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
668e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (start >= browser->top_idx) {
669e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		row = start - browser->top_idx;
670e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, row, column);
671e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_ULCORN_CHAR);
672e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, row, column + 1);
673e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_draw_hline(2);
674e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
675e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (row++ == 0)
676e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
677e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else
678e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		row = 0;
679e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
680e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (end >= browser->top_idx + browser->height)
681e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		end_row = browser->height - 1;
682e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
683e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		end_row = end - browser->top_idx;;
684e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
685e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__gotorc(browser, row, column);
686e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_draw_vline(end_row - row + 1);
687e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
688e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_browser__gotorc(browser, end_row, column);
689e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (end < browser->top_idx + browser->height) {
690e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_LLCORN_CHAR);
691e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, end_row, column + 1);
692e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_HLINE_CHAR);
693e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ui_browser__gotorc(browser, end_row, column + 2);
694e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		SLsmg_write_char(SLSMG_RARROW_CHAR);
695e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
696e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout:
697e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	SLsmg_set_char_set(0);
698e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
699e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
700e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
701e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			      u64 start, u64 end)
702e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
703e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (start > end)
704e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		__ui_browser__line_arrow_up(browser, column, start, end);
705e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
706e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		__ui_browser__line_arrow_down(browser, column, start, end);
707e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
708e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
709e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid ui_browser__init(void)
710e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
711e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i = 0;
712e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
713e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_config(ui_browser__color_config, NULL);
714e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
715e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (ui_browser__colorsets[i].name) {
716e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
717e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		sltt_set_color(c->colorset, c->name, c->fg, c->bg);
718e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
719e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
720e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	annotate_browser__init();
721e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
722