Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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         /* XXX more graceful overflow handling needed */
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 };