1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "libslang.h"
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "ui.h"
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <linux/compiler.h>
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <linux/list.h>
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <linux/rbtree.h>
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h>
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/ttydefaults.h>
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "browser.h"
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "helpline.h"
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../color.h"
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util.h"
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h>
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int ui_browser__percent_color(double percent, bool current)
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (current)
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return HE_COLORSET_SELECTED;
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (percent >= MIN_RED)
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return HE_COLORSET_TOP;
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (percent >= MIN_GREEN)
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return HE_COLORSET_MEDIUM;
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return HE_COLORSET_NORMAL;
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__set_color(struct ui_browser *self __used, int color)
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	SLsmg_set_color(color);
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__set_percent_color(struct ui_browser *self,
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   double percent, bool current)
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 int color = ui_browser__percent_color(percent, current);
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 ui_browser__set_color(self, color);
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__gotorc(struct ui_browser *self, int y, int x)
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	SLsmg_gotorc(self->y + y, self->x + x);
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct list_head *head = self->entries;
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct list_head *pos;
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	switch (whence) {
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_SET:
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pos = head->next;
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_CUR:
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pos = self->top;
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_END:
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pos = head->prev;
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	default:
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return;
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (offset > 0) {
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (offset-- != 0)
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pos = pos->next;
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (offset++ != 0)
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pos = pos->prev;
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->top = pos;
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_root *root = self->entries;
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	switch (whence) {
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_SET:
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nd = rb_first(root);
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_CUR:
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nd = self->top;
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case SEEK_END:
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nd = rb_last(root);
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	default:
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return;
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (offset > 0) {
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (offset-- != 0)
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			nd = rb_next(nd);
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (offset++ != 0)
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			nd = rb_prev(nd);
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->top = nd;
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengunsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int row = 0;
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->top == NULL)
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng                self->top = rb_first(self->entries);
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	nd = self->top;
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (nd != NULL) {
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__gotorc(self, row, 0);
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		self->write(self, nd, row);
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (++row == self->height)
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nd = rb_next(nd);
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return row;
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return self->top_idx + row == self->index;
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__refresh_dimensions(struct ui_browser *self)
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int cols, rows;
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtGetScreenSize(&cols, &rows);
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->width = cols - 1;
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->height = rows - 2;
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->y = 1;
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->x = 0;
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__reset_index(struct ui_browser *self)
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->index = self->top_idx = 0;
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->seek(self, 0, SEEK_SET);
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__add_exit_key(struct ui_browser *self, int key)
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtFormAddHotKey(self->form, key);
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i = 0;
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (keys[i] && i < 64) {
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__add_exit_key(self, keys[i]);
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		++i;
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid __ui_browser__show_title(struct ui_browser *browser, const char *title)
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	SLsmg_gotorc(0, 0);
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	slsmg_write_nstring(title, browser->width);
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__show_title(struct ui_browser *browser, const char *title)
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_lock(&ui__lock);
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	__ui_browser__show_title(browser, title);
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_unlock(&ui__lock);
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint ui_browser__show(struct ui_browser *self, const char *title,
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     const char *helpline, ...)
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list ap;
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->form != NULL)
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		newtFormDestroy(self->form);
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__refresh_dimensions(self);
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->form = newtForm(NULL, NULL, 0);
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->form == NULL)
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->sb = newtVerticalScrollbar(self->width, 1, self->height,
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					 HE_COLORSET_NORMAL,
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					 HE_COLORSET_SELECTED);
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->sb == NULL)
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_lock(&ui__lock);
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	__ui_browser__show_title(self, title);
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__add_exit_keys(self, keys);
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtFormAddComponent(self->form, self->sb);
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(ap, helpline);
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_helpline__vpush(helpline, ap);
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(ap);
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_unlock(&ui__lock);
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__hide(struct ui_browser *self)
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_lock(&ui__lock);
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtFormDestroy(self->form);
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->form = NULL;
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_helpline__pop();
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_unlock(&ui__lock);
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint ui_browser__refresh(struct ui_browser *self)
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int row;
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_lock(&ui__lock);
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	row = self->refresh(self);
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__set_color(self, HE_COLORSET_NORMAL);
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	SLsmg_fill_region(self->y + row, self->x,
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			  self->height - row, self->width, ' ');
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_unlock(&ui__lock);
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint ui_browser__run(struct ui_browser *self)
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct newtExitStruct es;
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ui_browser__refresh(self) < 0)
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (1) {
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		off_t offset;
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		newtFormRun(self->form, &es);
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (es.reason != NEWT_EXIT_HOTKEY)
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (es.u.key) {
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_DOWN:
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->index == self->nr_entries - 1)
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				break;
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			++self->index;
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->index == self->top_idx + self->height) {
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				++self->top_idx;
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				self->seek(self, +1, SEEK_CUR);
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_UP:
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->index == 0)
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				break;
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			--self->index;
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->index < self->top_idx) {
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				--self->top_idx;
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				self->seek(self, -1, SEEK_CUR);
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_PGDN:
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case ' ':
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->top_idx + self->height > self->nr_entries - 1)
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				break;
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			offset = self->height;
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->index + offset > self->nr_entries - 1)
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				offset = self->nr_entries - 1 - self->index;
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->index += offset;
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->top_idx += offset;
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->seek(self, +offset, SEEK_CUR);
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_PGUP:
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->top_idx == 0)
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				break;
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (self->top_idx < self->height)
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				offset = self->top_idx;
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				offset = self->height;
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->index -= offset;
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->top_idx -= offset;
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->seek(self, -offset, SEEK_CUR);
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_HOME:
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ui_browser__reset_index(self);
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_END:
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			offset = self->height - 1;
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (offset >= self->nr_entries)
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				offset = self->nr_entries - 1;
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->index = self->nr_entries - 1;
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->top_idx = self->index - offset;
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			self->seek(self, -offset, SEEK_END);
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:
304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return es.u.key;
305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ui_browser__refresh(self) < 0)
307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -1;
308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return -1;
310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengunsigned int ui_browser__list_head_refresh(struct ui_browser *self)
313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct list_head *pos;
315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct list_head *head = self->entries;
316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int row = 0;
317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->top == NULL || self->top == self->entries)
319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng                self->top = head->next;
320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pos = self->top;
322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_from(pos, head) {
324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__gotorc(self, row, 0);
325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		self->write(self, pos, row);
326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (++row == self->height)
327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return row;
331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct newtPercentTreeColors {
334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *topColorFg, *topColorBg;
335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *mediumColorFg, *mediumColorBg;
336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *normalColorFg, *normalColorBg;
337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *selColorFg, *selColorBg;
338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *codeColorFg, *codeColorBg;
339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} defaultPercentTreeColors = {
340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"red",       "lightgray",
341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"green",     "lightgray",
342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"black",     "lightgray",
343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"lightgray", "magenta",
344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"blue",	     "lightgray",
345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid ui_browser__init(void)
348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct newtPercentTreeColors *c = &defaultPercentTreeColors;
350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
357