Home | History | Annotate | Download | only in tui
      1 #include "../../util/util.h"
      2 #include <signal.h>
      3 #include <stdbool.h>
      4 #include <string.h>
      5 #include <sys/ttydefaults.h>
      6 
      7 #include "../../util/cache.h"
      8 #include "../../util/debug.h"
      9 #include "../browser.h"
     10 #include "../keysyms.h"
     11 #include "../helpline.h"
     12 #include "../ui.h"
     13 #include "../util.h"
     14 #include "../libslang.h"
     15 
     16 static void ui_browser__argv_write(struct ui_browser *browser,
     17 				   void *entry, int row)
     18 {
     19 	char **arg = entry;
     20 	bool current_entry = ui_browser__is_current_entry(browser, row);
     21 
     22 	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
     23 						       HE_COLORSET_NORMAL);
     24 	slsmg_write_nstring(*arg, browser->width);
     25 }
     26 
     27 static int popup_menu__run(struct ui_browser *menu)
     28 {
     29 	int key;
     30 
     31 	if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
     32 		return -1;
     33 
     34 	while (1) {
     35 		key = ui_browser__run(menu, 0);
     36 
     37 		switch (key) {
     38 		case K_RIGHT:
     39 		case K_ENTER:
     40 			key = menu->index;
     41 			break;
     42 		case K_LEFT:
     43 		case K_ESC:
     44 		case 'q':
     45 		case CTRL('c'):
     46 			key = -1;
     47 			break;
     48 		default:
     49 			continue;
     50 		}
     51 
     52 		break;
     53 	}
     54 
     55 	ui_browser__hide(menu);
     56 	return key;
     57 }
     58 
     59 int ui__popup_menu(int argc, char * const argv[])
     60 {
     61 	struct ui_browser menu = {
     62 		.entries    = (void *)argv,
     63 		.refresh    = ui_browser__argv_refresh,
     64 		.seek	    = ui_browser__argv_seek,
     65 		.write	    = ui_browser__argv_write,
     66 		.nr_entries = argc,
     67 	};
     68 
     69 	return popup_menu__run(&menu);
     70 }
     71 
     72 int ui_browser__input_window(const char *title, const char *text, char *input,
     73 			     const char *exit_msg, int delay_secs)
     74 {
     75 	int x, y, len, key;
     76 	int max_len = 60, nr_lines = 0;
     77 	static char buf[50];
     78 	const char *t;
     79 
     80 	t = text;
     81 	while (1) {
     82 		const char *sep = strchr(t, '\n');
     83 
     84 		if (sep == NULL)
     85 			sep = strchr(t, '\0');
     86 		len = sep - t;
     87 		if (max_len < len)
     88 			max_len = len;
     89 		++nr_lines;
     90 		if (*sep == '\0')
     91 			break;
     92 		t = sep + 1;
     93 	}
     94 
     95 	max_len += 2;
     96 	nr_lines += 8;
     97 	y = SLtt_Screen_Rows / 2 - nr_lines / 2;
     98 	x = SLtt_Screen_Cols / 2 - max_len / 2;
     99 
    100 	SLsmg_set_color(0);
    101 	SLsmg_draw_box(y, x++, nr_lines, max_len);
    102 	if (title) {
    103 		SLsmg_gotorc(y, x + 1);
    104 		SLsmg_write_string((char *)title);
    105 	}
    106 	SLsmg_gotorc(++y, x);
    107 	nr_lines -= 7;
    108 	max_len -= 2;
    109 	SLsmg_write_wrapped_string((unsigned char *)text, y, x,
    110 				   nr_lines, max_len, 1);
    111 	y += nr_lines;
    112 	len = 5;
    113 	while (len--) {
    114 		SLsmg_gotorc(y + len - 1, x);
    115 		SLsmg_write_nstring((char *)" ", max_len);
    116 	}
    117 	SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
    118 
    119 	SLsmg_gotorc(y + 3, x);
    120 	SLsmg_write_nstring((char *)exit_msg, max_len);
    121 	SLsmg_refresh();
    122 
    123 	x += 2;
    124 	len = 0;
    125 	key = ui__getch(delay_secs);
    126 	while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
    127 		if (key == K_BKSPC) {
    128 			if (len == 0)
    129 				goto next_key;
    130 			SLsmg_gotorc(y, x + --len);
    131 			SLsmg_write_char(' ');
    132 		} else {
    133 			buf[len] = key;
    134 			SLsmg_gotorc(y, x + len++);
    135 			SLsmg_write_char(key);
    136 		}
    137 		SLsmg_refresh();
    138 
    139 		/* XXX more graceful overflow handling needed */
    140 		if (len == sizeof(buf) - 1) {
    141 			ui_helpline__push("maximum size of symbol name reached!");
    142 			key = K_ENTER;
    143 			break;
    144 		}
    145 next_key:
    146 		key = ui__getch(delay_secs);
    147 	}
    148 
    149 	buf[len] = '\0';
    150 	strncpy(input, buf, len+1);
    151 	return key;
    152 }
    153 
    154 int ui__question_window(const char *title, const char *text,
    155 			const char *exit_msg, int delay_secs)
    156 {
    157 	int x, y;
    158 	int max_len = 0, nr_lines = 0;
    159 	const char *t;
    160 
    161 	t = text;
    162 	while (1) {
    163 		const char *sep = strchr(t, '\n');
    164 		int len;
    165 
    166 		if (sep == NULL)
    167 			sep = strchr(t, '\0');
    168 		len = sep - t;
    169 		if (max_len < len)
    170 			max_len = len;
    171 		++nr_lines;
    172 		if (*sep == '\0')
    173 			break;
    174 		t = sep + 1;
    175 	}
    176 
    177 	max_len += 2;
    178 	nr_lines += 4;
    179 	y = SLtt_Screen_Rows / 2 - nr_lines / 2,
    180 	x = SLtt_Screen_Cols / 2 - max_len / 2;
    181 
    182 	SLsmg_set_color(0);
    183 	SLsmg_draw_box(y, x++, nr_lines, max_len);
    184 	if (title) {
    185 		SLsmg_gotorc(y, x + 1);
    186 		SLsmg_write_string((char *)title);
    187 	}
    188 	SLsmg_gotorc(++y, x);
    189 	nr_lines -= 2;
    190 	max_len -= 2;
    191 	SLsmg_write_wrapped_string((unsigned char *)text, y, x,
    192 				   nr_lines, max_len, 1);
    193 	SLsmg_gotorc(y + nr_lines - 2, x);
    194 	SLsmg_write_nstring((char *)" ", max_len);
    195 	SLsmg_gotorc(y + nr_lines - 1, x);
    196 	SLsmg_write_nstring((char *)exit_msg, max_len);
    197 	SLsmg_refresh();
    198 	return ui__getch(delay_secs);
    199 }
    200 
    201 int ui__help_window(const char *text)
    202 {
    203 	return ui__question_window("Help", text, "Press any key...", 0);
    204 }
    205 
    206 int ui__dialog_yesno(const char *msg)
    207 {
    208 	return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
    209 }
    210 
    211 static int __ui__warning(const char *title, const char *format, va_list args)
    212 {
    213 	char *s;
    214 
    215 	if (vasprintf(&s, format, args) > 0) {
    216 		int key;
    217 
    218 		pthread_mutex_lock(&ui__lock);
    219 		key = ui__question_window(title, s, "Press any key...", 0);
    220 		pthread_mutex_unlock(&ui__lock);
    221 		free(s);
    222 		return key;
    223 	}
    224 
    225 	fprintf(stderr, "%s\n", title);
    226 	vfprintf(stderr, format, args);
    227 	return K_ESC;
    228 }
    229 
    230 static int perf_tui__error(const char *format, va_list args)
    231 {
    232 	return __ui__warning("Error:", format, args);
    233 }
    234 
    235 static int perf_tui__warning(const char *format, va_list args)
    236 {
    237 	return __ui__warning("Warning:", format, args);
    238 }
    239 
    240 struct perf_error_ops perf_tui_eops = {
    241 	.error		= perf_tui__error,
    242 	.warning	= perf_tui__warning,
    243 };
    244