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