162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include "ui/browser.h"
362306a36Sopenharmony_ci#include "ui/keysyms.h"
462306a36Sopenharmony_ci#include "ui/ui.h"
562306a36Sopenharmony_ci#include "ui/util.h"
662306a36Sopenharmony_ci#include "ui/libslang.h"
762306a36Sopenharmony_ci#include "util/header.h"
862306a36Sopenharmony_ci#include "util/session.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <sys/ttydefaults.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic void ui_browser__argv_write(struct ui_browser *browser,
1362306a36Sopenharmony_ci				   void *entry, int row)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	char **arg = entry;
1662306a36Sopenharmony_ci	char *str = *arg;
1762306a36Sopenharmony_ci	char empty[] = " ";
1862306a36Sopenharmony_ci	bool current_entry = ui_browser__is_current_entry(browser, row);
1962306a36Sopenharmony_ci	unsigned long offset = (unsigned long)browser->priv;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (offset >= strlen(str))
2262306a36Sopenharmony_ci		str = empty;
2362306a36Sopenharmony_ci	else
2462306a36Sopenharmony_ci		str = str + offset;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
2762306a36Sopenharmony_ci						       HE_COLORSET_NORMAL);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	ui_browser__write_nstring(browser, str, browser->width);
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic int list_menu__run(struct ui_browser *menu)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	int key;
3562306a36Sopenharmony_ci	unsigned long offset;
3662306a36Sopenharmony_ci	static const char help[] =
3762306a36Sopenharmony_ci	"h/?/F1        Show this window\n"
3862306a36Sopenharmony_ci	"UP/DOWN/PGUP\n"
3962306a36Sopenharmony_ci	"PGDN/SPACE\n"
4062306a36Sopenharmony_ci	"LEFT/RIGHT    Navigate\n"
4162306a36Sopenharmony_ci	"q/ESC/CTRL+C  Exit browser";
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
4462306a36Sopenharmony_ci		return -1;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	while (1) {
4762306a36Sopenharmony_ci		key = ui_browser__run(menu, 0);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci		switch (key) {
5062306a36Sopenharmony_ci		case K_RIGHT:
5162306a36Sopenharmony_ci			offset = (unsigned long)menu->priv;
5262306a36Sopenharmony_ci			offset += 10;
5362306a36Sopenharmony_ci			menu->priv = (void *)offset;
5462306a36Sopenharmony_ci			continue;
5562306a36Sopenharmony_ci		case K_LEFT:
5662306a36Sopenharmony_ci			offset = (unsigned long)menu->priv;
5762306a36Sopenharmony_ci			if (offset >= 10)
5862306a36Sopenharmony_ci				offset -= 10;
5962306a36Sopenharmony_ci			menu->priv = (void *)offset;
6062306a36Sopenharmony_ci			continue;
6162306a36Sopenharmony_ci		case K_F1:
6262306a36Sopenharmony_ci		case 'h':
6362306a36Sopenharmony_ci		case '?':
6462306a36Sopenharmony_ci			ui_browser__help_window(menu, help);
6562306a36Sopenharmony_ci			continue;
6662306a36Sopenharmony_ci		case K_ESC:
6762306a36Sopenharmony_ci		case 'q':
6862306a36Sopenharmony_ci		case CTRL('c'):
6962306a36Sopenharmony_ci			key = -1;
7062306a36Sopenharmony_ci			break;
7162306a36Sopenharmony_ci		default:
7262306a36Sopenharmony_ci			continue;
7362306a36Sopenharmony_ci		}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci		break;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	ui_browser__hide(menu);
7962306a36Sopenharmony_ci	return key;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic int ui__list_menu(int argc, char * const argv[])
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct ui_browser menu = {
8562306a36Sopenharmony_ci		.entries    = (void *)argv,
8662306a36Sopenharmony_ci		.refresh    = ui_browser__argv_refresh,
8762306a36Sopenharmony_ci		.seek	    = ui_browser__argv_seek,
8862306a36Sopenharmony_ci		.write	    = ui_browser__argv_write,
8962306a36Sopenharmony_ci		.nr_entries = argc,
9062306a36Sopenharmony_ci	};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	return list_menu__run(&menu);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciint tui__header_window(struct perf_env *env)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	int i, argc = 0;
9862306a36Sopenharmony_ci	char **argv;
9962306a36Sopenharmony_ci	struct perf_session *session;
10062306a36Sopenharmony_ci	char *ptr, *pos;
10162306a36Sopenharmony_ci	size_t size;
10262306a36Sopenharmony_ci	FILE *fp = open_memstream(&ptr, &size);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	session = container_of(env, struct perf_session, header.env);
10562306a36Sopenharmony_ci	perf_header__fprintf_info(session, fp, true);
10662306a36Sopenharmony_ci	fclose(fp);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
10962306a36Sopenharmony_ci		argc++;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	argv = calloc(argc + 1, sizeof(*argv));
11262306a36Sopenharmony_ci	if (argv == NULL)
11362306a36Sopenharmony_ci		goto out;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	argv[0] = pos = ptr;
11662306a36Sopenharmony_ci	for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
11762306a36Sopenharmony_ci		*pos++ = '\0';
11862306a36Sopenharmony_ci		argv[i] = pos;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	BUG_ON(i != argc + 1);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	ui__list_menu(argc, argv);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ciout:
12662306a36Sopenharmony_ci	free(argv);
12762306a36Sopenharmony_ci	free(ptr);
12862306a36Sopenharmony_ci	return 0;
12962306a36Sopenharmony_ci}
130