0
     SˆÑÚ„¿ÐÀØ )    S// SPDX-License-Identifier: GPL-2.0+
/*
 *  menubox.c -- implements the menu box
 *
 *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
 *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
 */

/*
 *  Changes by Clifford Wolf (god@clifford.at)
 *
 *  [ 1998-06-13 ]
 *
 *    *)  A bugfix for the Page-Down problem
 *
 *    *)  Formerly when I used Page Down and Page Up, the cursor would be set
 *        to the first position in the menu box.  Now lxdialog is a bit
 *        smarter and works more like other menu systems (just have a look at
 *        it).
 *
 *    *)  Formerly if I selected something my scrolling would be broken because
 *        lxdialog is re-invoked by the Menuconfig shell script, can't
 *        remember the last scrolling position, and just sets it so that the
 *        cursor is at the bottom of the box.  Now it writes the temporary file
 *        lxdialog.scrltmp which contains this information. The file is
 *        deleted by lxdialog if the user leaves a submenu or enters a new
 *        one, but it would be nice if Menuconfig could make another "rm -f"
 *        just to be sure.  Just try it out - you will recognise a difference!
 *
 *  [ 1998-06-14 ]
 *
 *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
 *        and menus change their size on the fly.
 *
 *    *)  If for some reason the last scrolling position is not saved by
 *        lxdialog, it sets the scrolling so that the selected item is in the
 *        middle of the menu box, not at the bottom.
 *
 * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
 * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
 * This fixes a bug in Menuconfig where using ' ' to descend into menus
 * would leave mis-synchronized lxdialog.scrltmp files lying around,
 * fscanf would read in 'scroll', and eventually that value would get used.
 */

#include "dialog.h"

static int menu_width, item_x;

/*
 * Print menu item
 */
static void do_print_item(WINDOW * win, const char *item, int line_y,
			  int selected, int hotkey)
{
	int j;
	char *menu_item = malloc(menu_width + 1);

	strncpy(menu_item, item, menu_width - item_x);
	menu_item[menu_width - item_x] = '\0';
	j = first_alpha(menu_item, "YyNnMmHh");

	/* Clear 'residue' of last item */
	wattrset(win, dlg.menubox.atr);
	wmove(win, line_y, 0);
#if OLD_NCURSES
	{
		int i;
		for (i = 0; i < menu_width; i++)
			waddch(win, ' ');
	}
#else
	wclrtoeol(win);
#endif
	wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
	mvwaddstr(win, line_y, item_x, menu_item);
	if (hotkey) {
		wattrset(win, selected ? dlg.tag_key_selected.atr
			 : dlg.tag_key.atr);
		mvwaddch(win, line_y, item_x + j, menu_item[j]);
	}
	if (selected) {
		wmove(win, line_y, item_x + 1);
	}
	free(menu_item);
	wrefresh(win);
}

#define print_item(index, choice, selected)				\
do {									\
	item_set(index);						\
	do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
} while (0)

/*
 * Print the scroll indicators.
 */
static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
			 int height)
{
	int cur_y, cur_x;

	getyx(win, cur_y, cur_x);

	wmove(win, y, x);

	if (scroll > 0) {
		wattrset(win, dlg.uarrow.atr);
		waddch(win, ACS_UARROW);
		waddstr(win, "(-)");
	} else {
		wattrset(win, dlg.menubox.atr);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
	}

	y = y + height + 1;
	wmove(win, y, x);
	wrefresh(win);

	if ((height < item_no) && (scroll + height < item_no)) {
		wattrset(win, dlg.darrow.atr);
		waddch(win, ACS_DARROW);
		waddstr(win, "(+)");
	} else {
		wattrset(win, dlg.menubox_border.atr);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
		waddch(win, ACS_HLINE);
	}

	wmove(win, cur_y, cur_x);
	wrefresh(win);
}

/*
 * Display the termination buttons.
 */
static void print_buttons(WINDOW * win, int height, int width, int selected)
{
	int x = width / 2 - 28;
	int y = height - 2;

	print_button(win, "Select", 