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