18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "ui/browser.h"
38c2ecf20Sopenharmony_ci#include "ui/keysyms.h"
48c2ecf20Sopenharmony_ci#include "ui/ui.h"
58c2ecf20Sopenharmony_ci#include "ui/util.h"
68c2ecf20Sopenharmony_ci#include "ui/libslang.h"
78c2ecf20Sopenharmony_ci#include "util/header.h"
88c2ecf20Sopenharmony_ci#include "util/session.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <sys/ttydefaults.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic void ui_browser__argv_write(struct ui_browser *browser,
138c2ecf20Sopenharmony_ci				   void *entry, int row)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	char **arg = entry;
168c2ecf20Sopenharmony_ci	char *str = *arg;
178c2ecf20Sopenharmony_ci	char empty[] = " ";
188c2ecf20Sopenharmony_ci	bool current_entry = ui_browser__is_current_entry(browser, row);
198c2ecf20Sopenharmony_ci	unsigned long offset = (unsigned long)browser->priv;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	if (offset >= strlen(str))
228c2ecf20Sopenharmony_ci		str = empty;
238c2ecf20Sopenharmony_ci	else
248c2ecf20Sopenharmony_ci		str = str + offset;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
278c2ecf20Sopenharmony_ci						       HE_COLORSET_NORMAL);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	ui_browser__write_nstring(browser, str, browser->width);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int list_menu__run(struct ui_browser *menu)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	int key;
358c2ecf20Sopenharmony_ci	unsigned long offset;
368c2ecf20Sopenharmony_ci	static const char help[] =
378c2ecf20Sopenharmony_ci	"h/?/F1        Show this window\n"
388c2ecf20Sopenharmony_ci	"UP/DOWN/PGUP\n"
398c2ecf20Sopenharmony_ci	"PGDN/SPACE\n"
408c2ecf20Sopenharmony_ci	"LEFT/RIGHT    Navigate\n"
418c2ecf20Sopenharmony_ci	"q/ESC/CTRL+C  Exit browser";
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
448c2ecf20Sopenharmony_ci		return -1;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	while (1) {
478c2ecf20Sopenharmony_ci		key = ui_browser__run(menu, 0);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci		switch (key) {
508c2ecf20Sopenharmony_ci		case K_RIGHT:
518c2ecf20Sopenharmony_ci			offset = (unsigned long)menu->priv;
528c2ecf20Sopenharmony_ci			offset += 10;
538c2ecf20Sopenharmony_ci			menu->priv = (void *)offset;
548c2ecf20Sopenharmony_ci			continue;
558c2ecf20Sopenharmony_ci		case K_LEFT:
568c2ecf20Sopenharmony_ci			offset = (unsigned long)menu->priv;
578c2ecf20Sopenharmony_ci			if (offset >= 10)
588c2ecf20Sopenharmony_ci				offset -= 10;
598c2ecf20Sopenharmony_ci			menu->priv = (void *)offset;
608c2ecf20Sopenharmony_ci			continue;
618c2ecf20Sopenharmony_ci		case K_F1:
628c2ecf20Sopenharmony_ci		case 'h':
638c2ecf20Sopenharmony_ci		case '?':
648c2ecf20Sopenharmony_ci			ui_browser__help_window(menu, help);
658c2ecf20Sopenharmony_ci			continue;
668c2ecf20Sopenharmony_ci		case K_ESC:
678c2ecf20Sopenharmony_ci		case 'q':
688c2ecf20Sopenharmony_ci		case CTRL('c'):
698c2ecf20Sopenharmony_ci			key = -1;
708c2ecf20Sopenharmony_ci			break;
718c2ecf20Sopenharmony_ci		default:
728c2ecf20Sopenharmony_ci			continue;
738c2ecf20Sopenharmony_ci		}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		break;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	ui_browser__hide(menu);
798c2ecf20Sopenharmony_ci	return key;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic int ui__list_menu(int argc, char * const argv[])
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct ui_browser menu = {
858c2ecf20Sopenharmony_ci		.entries    = (void *)argv,
868c2ecf20Sopenharmony_ci		.refresh    = ui_browser__argv_refresh,
878c2ecf20Sopenharmony_ci		.seek	    = ui_browser__argv_seek,
888c2ecf20Sopenharmony_ci		.write	    = ui_browser__argv_write,
898c2ecf20Sopenharmony_ci		.nr_entries = argc,
908c2ecf20Sopenharmony_ci	};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	return list_menu__run(&menu);
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ciint tui__header_window(struct perf_env *env)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	int i, argc = 0;
988c2ecf20Sopenharmony_ci	char **argv;
998c2ecf20Sopenharmony_ci	struct perf_session *session;
1008c2ecf20Sopenharmony_ci	char *ptr, *pos;
1018c2ecf20Sopenharmony_ci	size_t size;
1028c2ecf20Sopenharmony_ci	FILE *fp = open_memstream(&ptr, &size);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	session = container_of(env, struct perf_session, header.env);
1058c2ecf20Sopenharmony_ci	perf_header__fprintf_info(session, fp, true);
1068c2ecf20Sopenharmony_ci	fclose(fp);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
1098c2ecf20Sopenharmony_ci		argc++;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	argv = calloc(argc + 1, sizeof(*argv));
1128c2ecf20Sopenharmony_ci	if (argv == NULL)
1138c2ecf20Sopenharmony_ci		goto out;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	argv[0] = pos = ptr;
1168c2ecf20Sopenharmony_ci	for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
1178c2ecf20Sopenharmony_ci		*pos++ = '\0';
1188c2ecf20Sopenharmony_ci		argv[i] = pos;
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	BUG_ON(i != argc + 1);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	ui__list_menu(argc, argv);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ciout:
1268c2ecf20Sopenharmony_ci	free(argv);
1278c2ecf20Sopenharmony_ci	free(ptr);
1288c2ecf20Sopenharmony_ci	return 0;
1298c2ecf20Sopenharmony_ci}
130