cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nconf.gui.c (14878B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
      4 *
      5 * Derived from menuconfig.
      6 */
      7#include "nconf.h"
      8#include "lkc.h"
      9
     10int attr_normal;
     11int attr_main_heading;
     12int attr_main_menu_box;
     13int attr_main_menu_fore;
     14int attr_main_menu_back;
     15int attr_main_menu_grey;
     16int attr_main_menu_heading;
     17int attr_scrollwin_text;
     18int attr_scrollwin_heading;
     19int attr_scrollwin_box;
     20int attr_dialog_text;
     21int attr_dialog_menu_fore;
     22int attr_dialog_menu_back;
     23int attr_dialog_box;
     24int attr_input_box;
     25int attr_input_heading;
     26int attr_input_text;
     27int attr_input_field;
     28int attr_function_text;
     29int attr_function_highlight;
     30
     31#define COLOR_ATTR(_at, _fg, _bg, _hl) \
     32	{ .attr = &(_at), .has_color = true, .color_fg = _fg, .color_bg = _bg, .highlight = _hl }
     33#define NO_COLOR_ATTR(_at, _hl) \
     34	{ .attr = &(_at), .has_color = false, .highlight = _hl }
     35#define COLOR_DEFAULT		-1
     36
     37struct nconf_attr_param {
     38	int *attr;
     39	bool has_color;
     40	int color_fg;
     41	int color_bg;
     42	int highlight;
     43};
     44
     45static const struct nconf_attr_param color_theme_params[] = {
     46	COLOR_ATTR(attr_normal,			COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL),
     47	COLOR_ATTR(attr_main_heading,		COLOR_MAGENTA,	COLOR_DEFAULT,	A_BOLD | A_UNDERLINE),
     48	COLOR_ATTR(attr_main_menu_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL),
     49	COLOR_ATTR(attr_main_menu_fore,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_REVERSE),
     50	COLOR_ATTR(attr_main_menu_back,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL),
     51	COLOR_ATTR(attr_main_menu_grey,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL),
     52	COLOR_ATTR(attr_main_menu_heading,	COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD),
     53	COLOR_ATTR(attr_scrollwin_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL),
     54	COLOR_ATTR(attr_scrollwin_heading,	COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD),
     55	COLOR_ATTR(attr_scrollwin_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_BOLD),
     56	COLOR_ATTR(attr_dialog_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_BOLD),
     57	COLOR_ATTR(attr_dialog_menu_fore,	COLOR_RED,	COLOR_DEFAULT,	A_STANDOUT),
     58	COLOR_ATTR(attr_dialog_menu_back,	COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL),
     59	COLOR_ATTR(attr_dialog_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_BOLD),
     60	COLOR_ATTR(attr_input_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL),
     61	COLOR_ATTR(attr_input_heading,		COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD),
     62	COLOR_ATTR(attr_input_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL),
     63	COLOR_ATTR(attr_input_field,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_UNDERLINE),
     64	COLOR_ATTR(attr_function_text,		COLOR_YELLOW,	COLOR_DEFAULT,	A_REVERSE),
     65	COLOR_ATTR(attr_function_highlight,	COLOR_DEFAULT,	COLOR_DEFAULT,	A_BOLD),
     66	{ /* sentinel */ }
     67};
     68
     69static const struct nconf_attr_param no_color_theme_params[] = {
     70	NO_COLOR_ATTR(attr_normal,		A_NORMAL),
     71	NO_COLOR_ATTR(attr_main_heading,	A_BOLD | A_UNDERLINE),
     72	NO_COLOR_ATTR(attr_main_menu_box,	A_NORMAL),
     73	NO_COLOR_ATTR(attr_main_menu_fore,	A_STANDOUT),
     74	NO_COLOR_ATTR(attr_main_menu_back,	A_NORMAL),
     75	NO_COLOR_ATTR(attr_main_menu_grey,	A_NORMAL),
     76	NO_COLOR_ATTR(attr_main_menu_heading,	A_BOLD),
     77	NO_COLOR_ATTR(attr_scrollwin_text,	A_NORMAL),
     78	NO_COLOR_ATTR(attr_scrollwin_heading,	A_BOLD),
     79	NO_COLOR_ATTR(attr_scrollwin_box,	A_BOLD),
     80	NO_COLOR_ATTR(attr_dialog_text,		A_NORMAL),
     81	NO_COLOR_ATTR(attr_dialog_menu_fore,	A_STANDOUT),
     82	NO_COLOR_ATTR(attr_dialog_menu_back,	A_NORMAL),
     83	NO_COLOR_ATTR(attr_dialog_box,		A_BOLD),
     84	NO_COLOR_ATTR(attr_input_box,		A_BOLD),
     85	NO_COLOR_ATTR(attr_input_heading,	A_BOLD),
     86	NO_COLOR_ATTR(attr_input_text,		A_NORMAL),
     87	NO_COLOR_ATTR(attr_input_field,		A_UNDERLINE),
     88	NO_COLOR_ATTR(attr_function_text,	A_REVERSE),
     89	NO_COLOR_ATTR(attr_function_highlight,	A_BOLD),
     90	{ /* sentinel */ }
     91};
     92
     93void set_colors(void)
     94{
     95	const struct nconf_attr_param *p;
     96	int pair = 0;
     97
     98	if (has_colors()) {
     99		start_color();
    100		use_default_colors();
    101		p = color_theme_params;
    102	} else {
    103		p = no_color_theme_params;
    104	}
    105
    106	for (; p->attr; p++) {
    107		int attr = p->highlight;
    108
    109		if (p->has_color) {
    110			pair++;
    111			init_pair(pair, p->color_fg, p->color_bg);
    112			attr |= COLOR_PAIR(pair);
    113		}
    114
    115		*p->attr = attr;
    116	}
    117}
    118
    119/* this changes the windows attributes !!! */
    120void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs)
    121{
    122	wattrset(win, attrs);
    123	mvwprintw(win, y, (width - strlen(str)) / 2, "%s", str);
    124}
    125
    126int get_line_no(const char *text)
    127{
    128	int i;
    129	int total = 1;
    130
    131	if (!text)
    132		return 0;
    133
    134	for (i = 0; text[i] != '\0'; i++)
    135		if (text[i] == '\n')
    136			total++;
    137	return total;
    138}
    139
    140const char *get_line(const char *text, int line_no)
    141{
    142	int i;
    143	int lines = 0;
    144
    145	if (!text)
    146		return NULL;
    147
    148	for (i = 0; text[i] != '\0' && lines < line_no; i++)
    149		if (text[i] == '\n')
    150			lines++;
    151	return text+i;
    152}
    153
    154int get_line_length(const char *line)
    155{
    156	int res = 0;
    157	while (*line != '\0' && *line != '\n') {
    158		line++;
    159		res++;
    160	}
    161	return res;
    162}
    163
    164/* print all lines to the window. */
    165void fill_window(WINDOW *win, const char *text)
    166{
    167	int x, y;
    168	int total_lines = get_line_no(text);
    169	int i;
    170
    171	getmaxyx(win, y, x);
    172	/* do not go over end of line */
    173	total_lines = min(total_lines, y);
    174	for (i = 0; i < total_lines; i++) {
    175		char tmp[x+10];
    176		const char *line = get_line(text, i);
    177		int len = get_line_length(line);
    178		strncpy(tmp, line, min(len, x));
    179		tmp[len] = '\0';
    180		mvwprintw(win, i, 0, "%s", tmp);
    181	}
    182}
    183
    184/* get the message, and buttons.
    185 * each button must be a char*
    186 * return the selected button
    187 *
    188 * this dialog is used for 2 different things:
    189 * 1) show a text box, no buttons.
    190 * 2) show a dialog, with horizontal buttons
    191 */
    192int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
    193{
    194	va_list ap;
    195	char *btn;
    196	int btns_width = 0;
    197	int msg_lines = 0;
    198	int msg_width = 0;
    199	int total_width;
    200	int win_rows = 0;
    201	WINDOW *win;
    202	WINDOW *msg_win;
    203	WINDOW *menu_win;
    204	MENU *menu;
    205	ITEM *btns[btn_num+1];
    206	int i, x, y;
    207	int res = -1;
    208
    209
    210	va_start(ap, btn_num);
    211	for (i = 0; i < btn_num; i++) {
    212		btn = va_arg(ap, char *);
    213		btns[i] = new_item(btn, "");
    214		btns_width += strlen(btn)+1;
    215	}
    216	va_end(ap);
    217	btns[btn_num] = NULL;
    218
    219	/* find the widest line of msg: */
    220	msg_lines = get_line_no(msg);
    221	for (i = 0; i < msg_lines; i++) {
    222		const char *line = get_line(msg, i);
    223		int len = get_line_length(line);
    224		if (msg_width < len)
    225			msg_width = len;
    226	}
    227
    228	total_width = max(msg_width, btns_width);
    229	/* place dialog in middle of screen */
    230	y = (getmaxy(stdscr)-(msg_lines+4))/2;
    231	x = (getmaxx(stdscr)-(total_width+4))/2;
    232
    233
    234	/* create the windows */
    235	if (btn_num > 0)
    236		win_rows = msg_lines+4;
    237	else
    238		win_rows = msg_lines+2;
    239
    240	win = newwin(win_rows, total_width+4, y, x);
    241	keypad(win, TRUE);
    242	menu_win = derwin(win, 1, btns_width, win_rows-2,
    243			1+(total_width+2-btns_width)/2);
    244	menu = new_menu(btns);
    245	msg_win = derwin(win, win_rows-2, msg_width, 1,
    246			1+(total_width+2-msg_width)/2);
    247
    248	set_menu_fore(menu, attr_dialog_menu_fore);
    249	set_menu_back(menu, attr_dialog_menu_back);
    250
    251	wattrset(win, attr_dialog_box);
    252	box(win, 0, 0);
    253
    254	/* print message */
    255	wattrset(msg_win, attr_dialog_text);
    256	fill_window(msg_win, msg);
    257
    258	set_menu_win(menu, win);
    259	set_menu_sub(menu, menu_win);
    260	set_menu_format(menu, 1, btn_num);
    261	menu_opts_off(menu, O_SHOWDESC);
    262	menu_opts_off(menu, O_SHOWMATCH);
    263	menu_opts_on(menu, O_ONEVALUE);
    264	menu_opts_on(menu, O_NONCYCLIC);
    265	set_menu_mark(menu, "");
    266	post_menu(menu);
    267
    268
    269	touchwin(win);
    270	refresh_all_windows(main_window);
    271	while ((res = wgetch(win))) {
    272		switch (res) {
    273		case KEY_LEFT:
    274			menu_driver(menu, REQ_LEFT_ITEM);
    275			break;
    276		case KEY_RIGHT:
    277			menu_driver(menu, REQ_RIGHT_ITEM);
    278			break;
    279		case 10: /* ENTER */
    280		case 27: /* ESCAPE */
    281		case ' ':
    282		case KEY_F(F_BACK):
    283		case KEY_F(F_EXIT):
    284			break;
    285		}
    286		touchwin(win);
    287		refresh_all_windows(main_window);
    288
    289		if (res == 10 || res == ' ') {
    290			res = item_index(current_item(menu));
    291			break;
    292		} else if (res == 27 || res == KEY_F(F_BACK) ||
    293				res == KEY_F(F_EXIT)) {
    294			res = KEY_EXIT;
    295			break;
    296		}
    297	}
    298
    299	unpost_menu(menu);
    300	free_menu(menu);
    301	for (i = 0; i < btn_num; i++)
    302		free_item(btns[i]);
    303
    304	delwin(win);
    305	return res;
    306}
    307
    308int dialog_inputbox(WINDOW *main_window,
    309		const char *title, const char *prompt,
    310		const char *init, char **resultp, int *result_len)
    311{
    312	int prompt_lines = 0;
    313	int prompt_width = 0;
    314	WINDOW *win;
    315	WINDOW *prompt_win;
    316	WINDOW *form_win;
    317	PANEL *panel;
    318	int i, x, y, lines, columns, win_lines, win_cols;
    319	int res = -1;
    320	int cursor_position = strlen(init);
    321	int cursor_form_win;
    322	char *result = *resultp;
    323
    324	getmaxyx(stdscr, lines, columns);
    325
    326	if (strlen(init)+1 > *result_len) {
    327		*result_len = strlen(init)+1;
    328		*resultp = result = xrealloc(result, *result_len);
    329	}
    330
    331	/* find the widest line of msg: */
    332	prompt_lines = get_line_no(prompt);
    333	for (i = 0; i < prompt_lines; i++) {
    334		const char *line = get_line(prompt, i);
    335		int len = get_line_length(line);
    336		prompt_width = max(prompt_width, len);
    337	}
    338
    339	if (title)
    340		prompt_width = max(prompt_width, strlen(title));
    341
    342	win_lines = min(prompt_lines+6, lines-2);
    343	win_cols = min(prompt_width+7, columns-2);
    344	prompt_lines = max(win_lines-6, 0);
    345	prompt_width = max(win_cols-7, 0);
    346
    347	/* place dialog in middle of screen */
    348	y = (lines-win_lines)/2;
    349	x = (columns-win_cols)/2;
    350
    351	strncpy(result, init, *result_len);
    352
    353	/* create the windows */
    354	win = newwin(win_lines, win_cols, y, x);
    355	prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
    356	form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
    357	keypad(form_win, TRUE);
    358
    359	wattrset(form_win, attr_input_field);
    360
    361	wattrset(win, attr_input_box);
    362	box(win, 0, 0);
    363	wattrset(win, attr_input_heading);
    364	if (title)
    365		mvwprintw(win, 0, 3, "%s", title);
    366
    367	/* print message */
    368	wattrset(prompt_win, attr_input_text);
    369	fill_window(prompt_win, prompt);
    370
    371	mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
    372	cursor_form_win = min(cursor_position, prompt_width-1);
    373	mvwprintw(form_win, 0, 0, "%s",
    374		  result + cursor_position-cursor_form_win);
    375
    376	/* create panels */
    377	panel = new_panel(win);
    378
    379	/* show the cursor */
    380	curs_set(1);
    381
    382	touchwin(win);
    383	refresh_all_windows(main_window);
    384	while ((res = wgetch(form_win))) {
    385		int len = strlen(result);
    386		switch (res) {
    387		case 10: /* ENTER */
    388		case 27: /* ESCAPE */
    389		case KEY_F(F_HELP):
    390		case KEY_F(F_EXIT):
    391		case KEY_F(F_BACK):
    392			break;
    393		case 8:   /* ^H */
    394		case 127: /* ^? */
    395		case KEY_BACKSPACE:
    396			if (cursor_position > 0) {
    397				memmove(&result[cursor_position-1],
    398						&result[cursor_position],
    399						len-cursor_position+1);
    400				cursor_position--;
    401				cursor_form_win--;
    402				len--;
    403			}
    404			break;
    405		case KEY_DC:
    406			if (cursor_position >= 0 && cursor_position < len) {
    407				memmove(&result[cursor_position],
    408						&result[cursor_position+1],
    409						len-cursor_position+1);
    410				len--;
    411			}
    412			break;
    413		case KEY_UP:
    414		case KEY_RIGHT:
    415			if (cursor_position < len) {
    416				cursor_position++;
    417				cursor_form_win++;
    418			}
    419			break;
    420		case KEY_DOWN:
    421		case KEY_LEFT:
    422			if (cursor_position > 0) {
    423				cursor_position--;
    424				cursor_form_win--;
    425			}
    426			break;
    427		case KEY_HOME:
    428			cursor_position = 0;
    429			cursor_form_win = 0;
    430			break;
    431		case KEY_END:
    432			cursor_position = len;
    433			cursor_form_win = min(cursor_position, prompt_width-1);
    434			break;
    435		default:
    436			if ((isgraph(res) || isspace(res))) {
    437				/* one for new char, one for '\0' */
    438				if (len+2 > *result_len) {
    439					*result_len = len+2;
    440					*resultp = result = realloc(result,
    441								*result_len);
    442				}
    443				/* insert the char at the proper position */
    444				memmove(&result[cursor_position+1],
    445						&result[cursor_position],
    446						len-cursor_position+1);
    447				result[cursor_position] = res;
    448				cursor_position++;
    449				cursor_form_win++;
    450				len++;
    451			} else {
    452				mvprintw(0, 0, "unknown key: %d\n", res);
    453			}
    454			break;
    455		}
    456		if (cursor_form_win < 0)
    457			cursor_form_win = 0;
    458		else if (cursor_form_win > prompt_width-1)
    459			cursor_form_win = prompt_width-1;
    460
    461		wmove(form_win, 0, 0);
    462		wclrtoeol(form_win);
    463		mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
    464		mvwprintw(form_win, 0, 0, "%s",
    465			result + cursor_position-cursor_form_win);
    466		wmove(form_win, 0, cursor_form_win);
    467		touchwin(win);
    468		refresh_all_windows(main_window);
    469
    470		if (res == 10) {
    471			res = 0;
    472			break;
    473		} else if (res == 27 || res == KEY_F(F_BACK) ||
    474				res == KEY_F(F_EXIT)) {
    475			res = KEY_EXIT;
    476			break;
    477		} else if (res == KEY_F(F_HELP)) {
    478			res = 1;
    479			break;
    480		}
    481	}
    482
    483	/* hide the cursor */
    484	curs_set(0);
    485	del_panel(panel);
    486	delwin(prompt_win);
    487	delwin(form_win);
    488	delwin(win);
    489	return res;
    490}
    491
    492/* refresh all windows in the correct order */
    493void refresh_all_windows(WINDOW *main_window)
    494{
    495	update_panels();
    496	touchwin(main_window);
    497	refresh();
    498}
    499
    500/* layman's scrollable window... */
    501void show_scroll_win(WINDOW *main_window,
    502		const char *title,
    503		const char *text)
    504{
    505	int res;
    506	int total_lines = get_line_no(text);
    507	int x, y, lines, columns;
    508	int start_x = 0, start_y = 0;
    509	int text_lines = 0, text_cols = 0;
    510	int total_cols = 0;
    511	int win_cols = 0;
    512	int win_lines = 0;
    513	int i = 0;
    514	WINDOW *win;
    515	WINDOW *pad;
    516	PANEL *panel;
    517
    518	getmaxyx(stdscr, lines, columns);
    519
    520	/* find the widest line of msg: */
    521	total_lines = get_line_no(text);
    522	for (i = 0; i < total_lines; i++) {
    523		const char *line = get_line(text, i);
    524		int len = get_line_length(line);
    525		total_cols = max(total_cols, len+2);
    526	}
    527
    528	/* create the pad */
    529	pad = newpad(total_lines+10, total_cols+10);
    530	wattrset(pad, attr_scrollwin_text);
    531	fill_window(pad, text);
    532
    533	win_lines = min(total_lines+4, lines-2);
    534	win_cols = min(total_cols+2, columns-2);
    535	text_lines = max(win_lines-4, 0);
    536	text_cols = max(win_cols-2, 0);
    537
    538	/* place window in middle of screen */
    539	y = (lines-win_lines)/2;
    540	x = (columns-win_cols)/2;
    541
    542	win = newwin(win_lines, win_cols, y, x);
    543	keypad(win, TRUE);
    544	/* show the help in the help window, and show the help panel */
    545	wattrset(win, attr_scrollwin_box);
    546	box(win, 0, 0);
    547	wattrset(win, attr_scrollwin_heading);
    548	mvwprintw(win, 0, 3, " %s ", title);
    549	panel = new_panel(win);
    550
    551	/* handle scrolling */
    552	do {
    553
    554		copywin(pad, win, start_y, start_x, 2, 2, text_lines,
    555				text_cols, 0);
    556		print_in_middle(win,
    557				text_lines+2,
    558				text_cols,
    559				"<OK>",
    560				attr_dialog_menu_fore);
    561		wrefresh(win);
    562
    563		res = wgetch(win);
    564		switch (res) {
    565		case KEY_NPAGE:
    566		case ' ':
    567		case 'd':
    568			start_y += text_lines-2;
    569			break;
    570		case KEY_PPAGE:
    571		case 'u':
    572			start_y -= text_lines+2;
    573			break;
    574		case KEY_HOME:
    575			start_y = 0;
    576			break;
    577		case KEY_END:
    578			start_y = total_lines-text_lines;
    579			break;
    580		case KEY_DOWN:
    581		case 'j':
    582			start_y++;
    583			break;
    584		case KEY_UP:
    585		case 'k':
    586			start_y--;
    587			break;
    588		case KEY_LEFT:
    589		case 'h':
    590			start_x--;
    591			break;
    592		case KEY_RIGHT:
    593		case 'l':
    594			start_x++;
    595			break;
    596		}
    597		if (res == 10 || res == 27 || res == 'q' ||
    598			res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
    599			res == KEY_F(F_EXIT))
    600			break;
    601		if (start_y < 0)
    602			start_y = 0;
    603		if (start_y >= total_lines-text_lines)
    604			start_y = total_lines-text_lines;
    605		if (start_x < 0)
    606			start_x = 0;
    607		if (start_x >= total_cols-text_cols)
    608			start_x = total_cols-text_cols;
    609	} while (res);
    610
    611	del_panel(panel);
    612	delwin(win);
    613	refresh_all_windows(main_window);
    614}