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