| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | #include "../../util/util.h"
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <stdbool.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <sys/ttydefaults.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../../util/cache.h"
 | 
					
						
							|  |  |  | #include "../../util/debug.h"
 | 
					
						
							|  |  |  | #include "../browser.h"
 | 
					
						
							|  |  |  | #include "../keysyms.h"
 | 
					
						
							|  |  |  | #include "../helpline.h"
 | 
					
						
							|  |  |  | #include "../ui.h"
 | 
					
						
							|  |  |  | #include "../util.h"
 | 
					
						
							|  |  |  | #include "../libslang.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ui_browser__argv_write(struct ui_browser *browser, | 
					
						
							|  |  |  | 				   void *entry, int row) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char **arg = entry; | 
					
						
							|  |  |  | 	bool current_entry = ui_browser__is_current_entry(browser, row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : | 
					
						
							|  |  |  | 						       HE_COLORSET_NORMAL); | 
					
						
							|  |  |  | 	slsmg_write_nstring(*arg, browser->width); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int popup_menu__run(struct ui_browser *menu) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		key = ui_browser__run(menu, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (key) { | 
					
						
							|  |  |  | 		case K_RIGHT: | 
					
						
							|  |  |  | 		case K_ENTER: | 
					
						
							|  |  |  | 			key = menu->index; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case K_LEFT: | 
					
						
							|  |  |  | 		case K_ESC: | 
					
						
							|  |  |  | 		case 'q': | 
					
						
							|  |  |  | 		case CTRL('c'): | 
					
						
							|  |  |  | 			key = -1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ui_browser__hide(menu); | 
					
						
							|  |  |  | 	return key; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ui__popup_menu(int argc, char * const argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ui_browser menu = { | 
					
						
							|  |  |  | 		.entries    = (void *)argv, | 
					
						
							|  |  |  | 		.refresh    = ui_browser__argv_refresh, | 
					
						
							|  |  |  | 		.seek	    = ui_browser__argv_seek, | 
					
						
							|  |  |  | 		.write	    = ui_browser__argv_write, | 
					
						
							|  |  |  | 		.nr_entries = argc, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return popup_menu__run(&menu); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ui_browser__input_window(const char *title, const char *text, char *input, | 
					
						
							|  |  |  | 			     const char *exit_msg, int delay_secs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int x, y, len, key; | 
					
						
							|  |  |  | 	int max_len = 60, nr_lines = 0; | 
					
						
							|  |  |  | 	static char buf[50]; | 
					
						
							|  |  |  | 	const char *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t = text; | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		const char *sep = strchr(t, '\n'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (sep == NULL) | 
					
						
							|  |  |  | 			sep = strchr(t, '\0'); | 
					
						
							|  |  |  | 		len = sep - t; | 
					
						
							|  |  |  | 		if (max_len < len) | 
					
						
							|  |  |  | 			max_len = len; | 
					
						
							|  |  |  | 		++nr_lines; | 
					
						
							|  |  |  | 		if (*sep == '\0') | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		t = sep + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 	pthread_mutex_lock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 	max_len += 2; | 
					
						
							|  |  |  | 	nr_lines += 8; | 
					
						
							|  |  |  | 	y = SLtt_Screen_Rows / 2 - nr_lines / 2; | 
					
						
							|  |  |  | 	x = SLtt_Screen_Cols / 2 - max_len / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SLsmg_set_color(0); | 
					
						
							|  |  |  | 	SLsmg_draw_box(y, x++, nr_lines, max_len); | 
					
						
							|  |  |  | 	if (title) { | 
					
						
							|  |  |  | 		SLsmg_gotorc(y, x + 1); | 
					
						
							|  |  |  | 		SLsmg_write_string((char *)title); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	SLsmg_gotorc(++y, x); | 
					
						
							|  |  |  | 	nr_lines -= 7; | 
					
						
							|  |  |  | 	max_len -= 2; | 
					
						
							|  |  |  | 	SLsmg_write_wrapped_string((unsigned char *)text, y, x, | 
					
						
							|  |  |  | 				   nr_lines, max_len, 1); | 
					
						
							|  |  |  | 	y += nr_lines; | 
					
						
							|  |  |  | 	len = 5; | 
					
						
							|  |  |  | 	while (len--) { | 
					
						
							|  |  |  | 		SLsmg_gotorc(y + len - 1, x); | 
					
						
							|  |  |  | 		SLsmg_write_nstring((char *)" ", max_len); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	SLsmg_draw_box(y++, x + 1, 3, max_len - 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SLsmg_gotorc(y + 3, x); | 
					
						
							|  |  |  | 	SLsmg_write_nstring((char *)exit_msg, max_len); | 
					
						
							|  |  |  | 	SLsmg_refresh(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 	pthread_mutex_unlock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 	x += 2; | 
					
						
							|  |  |  | 	len = 0; | 
					
						
							|  |  |  | 	key = ui__getch(delay_secs); | 
					
						
							|  |  |  | 	while (key != K_TIMER && key != K_ENTER && key != K_ESC) { | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 		pthread_mutex_lock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 		if (key == K_BKSPC) { | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 			if (len == 0) { | 
					
						
							|  |  |  | 				pthread_mutex_unlock(&ui__lock); | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 				goto next_key; | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 			SLsmg_gotorc(y, x + --len); | 
					
						
							|  |  |  | 			SLsmg_write_char(' '); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			buf[len] = key; | 
					
						
							|  |  |  | 			SLsmg_gotorc(y, x + len++); | 
					
						
							|  |  |  | 			SLsmg_write_char(key); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		SLsmg_refresh(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 		pthread_mutex_unlock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 		/* XXX more graceful overflow handling needed */ | 
					
						
							|  |  |  | 		if (len == sizeof(buf) - 1) { | 
					
						
							|  |  |  | 			ui_helpline__push("maximum size of symbol name reached!"); | 
					
						
							|  |  |  | 			key = K_ENTER; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | next_key: | 
					
						
							|  |  |  | 		key = ui__getch(delay_secs); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf[len] = '\0'; | 
					
						
							|  |  |  | 	strncpy(input, buf, len+1); | 
					
						
							|  |  |  | 	return key; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ui__question_window(const char *title, const char *text, | 
					
						
							|  |  |  | 			const char *exit_msg, int delay_secs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int x, y; | 
					
						
							|  |  |  | 	int max_len = 0, nr_lines = 0; | 
					
						
							|  |  |  | 	const char *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t = text; | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		const char *sep = strchr(t, '\n'); | 
					
						
							|  |  |  | 		int len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (sep == NULL) | 
					
						
							|  |  |  | 			sep = strchr(t, '\0'); | 
					
						
							|  |  |  | 		len = sep - t; | 
					
						
							|  |  |  | 		if (max_len < len) | 
					
						
							|  |  |  | 			max_len = len; | 
					
						
							|  |  |  | 		++nr_lines; | 
					
						
							|  |  |  | 		if (*sep == '\0') | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		t = sep + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 	pthread_mutex_lock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 	max_len += 2; | 
					
						
							|  |  |  | 	nr_lines += 4; | 
					
						
							|  |  |  | 	y = SLtt_Screen_Rows / 2 - nr_lines / 2, | 
					
						
							|  |  |  | 	x = SLtt_Screen_Cols / 2 - max_len / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SLsmg_set_color(0); | 
					
						
							|  |  |  | 	SLsmg_draw_box(y, x++, nr_lines, max_len); | 
					
						
							|  |  |  | 	if (title) { | 
					
						
							|  |  |  | 		SLsmg_gotorc(y, x + 1); | 
					
						
							|  |  |  | 		SLsmg_write_string((char *)title); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	SLsmg_gotorc(++y, x); | 
					
						
							|  |  |  | 	nr_lines -= 2; | 
					
						
							|  |  |  | 	max_len -= 2; | 
					
						
							|  |  |  | 	SLsmg_write_wrapped_string((unsigned char *)text, y, x, | 
					
						
							|  |  |  | 				   nr_lines, max_len, 1); | 
					
						
							|  |  |  | 	SLsmg_gotorc(y + nr_lines - 2, x); | 
					
						
							|  |  |  | 	SLsmg_write_nstring((char *)" ", max_len); | 
					
						
							|  |  |  | 	SLsmg_gotorc(y + nr_lines - 1, x); | 
					
						
							|  |  |  | 	SLsmg_write_nstring((char *)exit_msg, max_len); | 
					
						
							|  |  |  | 	SLsmg_refresh(); | 
					
						
							| 
									
										
										
										
											2013-12-26 14:37:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pthread_mutex_unlock(&ui__lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-29 13:22:58 +09:00
										 |  |  | 	return ui__getch(delay_secs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ui__help_window(const char *text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ui__question_window("Help", text, "Press any key...", 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ui__dialog_yesno(const char *msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __ui__warning(const char *title, const char *format, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (vasprintf(&s, format, args) > 0) { | 
					
						
							|  |  |  | 		int key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		key = ui__question_window(title, s, "Press any key...", 0); | 
					
						
							|  |  |  | 		free(s); | 
					
						
							|  |  |  | 		return key; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(stderr, "%s\n", title); | 
					
						
							|  |  |  | 	vfprintf(stderr, format, args); | 
					
						
							|  |  |  | 	return K_ESC; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int perf_tui__error(const char *format, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return __ui__warning("Error:", format, args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int perf_tui__warning(const char *format, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return __ui__warning("Warning:", format, args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct perf_error_ops perf_tui_eops = { | 
					
						
							|  |  |  | 	.error		= perf_tui__error, | 
					
						
							|  |  |  | 	.warning	= perf_tui__warning, | 
					
						
							|  |  |  | }; |