0001
0002 #include <signal.h>
0003 #include <stdbool.h>
0004 #include <string.h>
0005 #include <stdlib.h>
0006 #include <sys/ttydefaults.h>
0007
0008 #include "../browser.h"
0009 #include "../keysyms.h"
0010 #include "../helpline.h"
0011 #include "../ui.h"
0012 #include "../util.h"
0013 #include "../libslang.h"
0014
0015 static void ui_browser__argv_write(struct ui_browser *browser,
0016 void *entry, int row)
0017 {
0018 char **arg = entry;
0019 bool current_entry = ui_browser__is_current_entry(browser, row);
0020
0021 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
0022 HE_COLORSET_NORMAL);
0023 ui_browser__write_nstring(browser, *arg, browser->width);
0024 }
0025
0026 static int popup_menu__run(struct ui_browser *menu, int *keyp)
0027 {
0028 int key;
0029
0030 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
0031 return -1;
0032
0033 while (1) {
0034 key = ui_browser__run(menu, 0);
0035
0036 switch (key) {
0037 case K_RIGHT:
0038 case K_ENTER:
0039 key = menu->index;
0040 break;
0041 case K_LEFT:
0042 case K_ESC:
0043 case 'q':
0044 case CTRL('c'):
0045 key = -1;
0046 break;
0047 default:
0048 if (keyp) {
0049 *keyp = key;
0050 key = menu->nr_entries;
0051 break;
0052 }
0053 continue;
0054 }
0055
0056 break;
0057 }
0058
0059 ui_browser__hide(menu);
0060 return key;
0061 }
0062
0063 int ui__popup_menu(int argc, char * const argv[], int *keyp)
0064 {
0065 struct ui_browser menu = {
0066 .entries = (void *)argv,
0067 .refresh = ui_browser__argv_refresh,
0068 .seek = ui_browser__argv_seek,
0069 .write = ui_browser__argv_write,
0070 .nr_entries = argc,
0071 };
0072 return popup_menu__run(&menu, keyp);
0073 }
0074
0075 int ui_browser__input_window(const char *title, const char *text, char *input,
0076 const char *exit_msg, int delay_secs)
0077 {
0078 int x, y, len, key;
0079 int max_len = 60, nr_lines = 0;
0080 static char buf[50];
0081 const char *t;
0082
0083 t = text;
0084 while (1) {
0085 const char *sep = strchr(t, '\n');
0086
0087 if (sep == NULL)
0088 sep = strchr(t, '\0');
0089 len = sep - t;
0090 if (max_len < len)
0091 max_len = len;
0092 ++nr_lines;
0093 if (*sep == '\0')
0094 break;
0095 t = sep + 1;
0096 }
0097
0098 pthread_mutex_lock(&ui__lock);
0099
0100 max_len += 2;
0101 nr_lines += 8;
0102 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
0103 x = SLtt_Screen_Cols / 2 - max_len / 2;
0104
0105 SLsmg_set_color(0);
0106 SLsmg_draw_box(y, x++, nr_lines, max_len);
0107 if (title) {
0108 SLsmg_gotorc(y, x + 1);
0109 SLsmg_write_string((char *)title);
0110 }
0111 SLsmg_gotorc(++y, x);
0112 nr_lines -= 7;
0113 max_len -= 2;
0114 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
0115 nr_lines, max_len, 1);
0116 y += nr_lines;
0117 len = 5;
0118 while (len--) {
0119 SLsmg_gotorc(y + len - 1, x);
0120 SLsmg_write_nstring((char *)" ", max_len);
0121 }
0122 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
0123
0124 SLsmg_gotorc(y + 3, x);
0125 SLsmg_write_nstring((char *)exit_msg, max_len);
0126 SLsmg_refresh();
0127
0128 pthread_mutex_unlock(&ui__lock);
0129
0130 x += 2;
0131 len = 0;
0132 key = ui__getch(delay_secs);
0133 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
0134 pthread_mutex_lock(&ui__lock);
0135
0136 if (key == K_BKSPC) {
0137 if (len == 0) {
0138 pthread_mutex_unlock(&ui__lock);
0139 goto next_key;
0140 }
0141 SLsmg_gotorc(y, x + --len);
0142 SLsmg_write_char(' ');
0143 } else {
0144 buf[len] = key;
0145 SLsmg_gotorc(y, x + len++);
0146 SLsmg_write_char(key);
0147 }
0148 SLsmg_refresh();
0149
0150 pthread_mutex_unlock(&ui__lock);
0151
0152
0153 if (len == sizeof(buf) - 1) {
0154 ui_helpline__push("maximum size of symbol name reached!");
0155 key = K_ENTER;
0156 break;
0157 }
0158 next_key:
0159 key = ui__getch(delay_secs);
0160 }
0161
0162 buf[len] = '\0';
0163 strncpy(input, buf, len+1);
0164 return key;
0165 }
0166
0167 void __ui__info_window(const char *title, const char *text, const char *exit_msg)
0168 {
0169 int x, y;
0170 int max_len = 0, nr_lines = 0;
0171 const char *t;
0172
0173 t = text;
0174 while (1) {
0175 const char *sep = strchr(t, '\n');
0176 int len;
0177
0178 if (sep == NULL)
0179 sep = strchr(t, '\0');
0180 len = sep - t;
0181 if (max_len < len)
0182 max_len = len;
0183 ++nr_lines;
0184 if (*sep == '\0')
0185 break;
0186 t = sep + 1;
0187 }
0188
0189 max_len += 2;
0190 nr_lines += 2;
0191 if (exit_msg)
0192 nr_lines += 2;
0193 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
0194 x = SLtt_Screen_Cols / 2 - max_len / 2;
0195
0196 SLsmg_set_color(0);
0197 SLsmg_draw_box(y, x++, nr_lines, max_len);
0198 if (title) {
0199 SLsmg_gotorc(y, x + 1);
0200 SLsmg_write_string((char *)title);
0201 }
0202 SLsmg_gotorc(++y, x);
0203 if (exit_msg)
0204 nr_lines -= 2;
0205 max_len -= 2;
0206 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
0207 nr_lines, max_len, 1);
0208 if (exit_msg) {
0209 SLsmg_gotorc(y + nr_lines - 2, x);
0210 SLsmg_write_nstring((char *)" ", max_len);
0211 SLsmg_gotorc(y + nr_lines - 1, x);
0212 SLsmg_write_nstring((char *)exit_msg, max_len);
0213 }
0214 }
0215
0216 void ui__info_window(const char *title, const char *text)
0217 {
0218 pthread_mutex_lock(&ui__lock);
0219 __ui__info_window(title, text, NULL);
0220 SLsmg_refresh();
0221 pthread_mutex_unlock(&ui__lock);
0222 }
0223
0224 int ui__question_window(const char *title, const char *text,
0225 const char *exit_msg, int delay_secs)
0226 {
0227 pthread_mutex_lock(&ui__lock);
0228 __ui__info_window(title, text, exit_msg);
0229 SLsmg_refresh();
0230 pthread_mutex_unlock(&ui__lock);
0231 return ui__getch(delay_secs);
0232 }
0233
0234 int ui__help_window(const char *text)
0235 {
0236 return ui__question_window("Help", text, "Press any key...", 0);
0237 }
0238
0239 int ui__dialog_yesno(const char *msg)
0240 {
0241 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
0242 }
0243
0244 static int __ui__warning(const char *title, const char *format, va_list args)
0245 {
0246 char *s;
0247
0248 if (vasprintf(&s, format, args) > 0) {
0249 int key;
0250
0251 key = ui__question_window(title, s, "Press any key...", 0);
0252 free(s);
0253 return key;
0254 }
0255
0256 fprintf(stderr, "%s\n", title);
0257 vfprintf(stderr, format, args);
0258 return K_ESC;
0259 }
0260
0261 static int perf_tui__error(const char *format, va_list args)
0262 {
0263 return __ui__warning("Error:", format, args);
0264 }
0265
0266 static int perf_tui__warning(const char *format, va_list args)
0267 {
0268 return __ui__warning("Warning:", format, args);
0269 }
0270
0271 struct perf_error_ops perf_tui_eops = {
0272 .error = perf_tui__error,
0273 .warning = perf_tui__warning,
0274 };