244 lines
		
	
	
	
		
			5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			244 lines
		
	
	
	
		
			5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#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;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									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();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									x += 2;
							 | 
						||
| 
								 | 
							
									len = 0;
							 | 
						||
| 
								 | 
							
									key = ui__getch(delay_secs);
							 | 
						||
| 
								 | 
							
									while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
							 | 
						||
| 
								 | 
							
										if (key == K_BKSPC) {
							 | 
						||
| 
								 | 
							
											if (len == 0)
							 | 
						||
| 
								 | 
							
												goto next_key;
							 | 
						||
| 
								 | 
							
											SLsmg_gotorc(y, x + --len);
							 | 
						||
| 
								 | 
							
											SLsmg_write_char(' ');
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											buf[len] = key;
							 | 
						||
| 
								 | 
							
											SLsmg_gotorc(y, x + len++);
							 | 
						||
| 
								 | 
							
											SLsmg_write_char(key);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										SLsmg_refresh();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 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;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									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();
							 | 
						||
| 
								 | 
							
									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;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										pthread_mutex_lock(&ui__lock);
							 | 
						||
| 
								 | 
							
										key = ui__question_window(title, s, "Press any key...", 0);
							 | 
						||
| 
								 | 
							
										pthread_mutex_unlock(&ui__lock);
							 | 
						||
| 
								 | 
							
										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,
							 | 
						||
| 
								 | 
							
								};
							 |