/*
 *  inputbox.c -- implements the input box
 *
 *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
 *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "dialog.h"

char dialog_input_result[MAX_LEN + 1];

/*
 *  Print the termination buttons
 */
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{
	int x = width / 2 - 11;
	int y = height - 2;

	print_button(dialog, gettext("  Ok  "), y, x, selected == 0);
	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);

	wmove(dialog, y, x + 1 + 14 * selected);
	wrefresh(dialog);
}

/*
 * Display a dialog box for inputing a string
 */
int dialog_inputbox(const char *title, const char *prompt, int height, int width,
		    const char *init)
{
	int i, x, y, box_y, box_x, box_width;
	int input_x = 0, key = 0, button = -1;
	int show_x, len, pos;
	char *instr = dialog_input_result;
	WINDOW *dialog;

	if (!init)
		instr[0] = '\0';
	else
		strcpy(instr, init);

do_resize:
	if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
		return -ERRDISPLAYTOOSMALL;
	if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
		return -ERRDISPLAYTOOSMALL;

	/* center dialog box on screen */
	x = (getmaxx(stdscr) - width) / 2;
	y = (getmaxy(stdscr) - height) / 2;

	draw_shadow(stdscr, y, x, height, width);

	dialog = newwin(height, width, y, x);
	keypad(dialog, TRUE);

	draw_box(dialog, 0, 0, height, width,
		 dlg.dialog.atr, dlg.border.atr);
	wattrset(dialog, dlg.border.atr);
	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
	for (i = 0; i < width - 2; i++)
		waddch(dialog, ACS_HLINE);
	wattrset(dialog, dlg.dialog.atr);
	waddch(dialog, ACS_RTEE);

	print_title(dialog, title, width);

	wattrset(dialog, dlg.dialog.atr);
	print_autowrap(dialog, prompt, width - 2, 1, 3);

	/* Draw the input field box */
	box_width = width - 6;
	getyx(dialog, y, x);
	box_y = y + 2;
	box_x = (width - box_width) / 2;
	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
		 dlg.dialog.atr, dlg.border.atr);

	print_buttons(dialog, height, width, 0);

	/* Set up the initial value */
	wmove(dialog, box_y, box_x);
	wattrset(dialog, dlg.inputbox.atr);

	len = strlen(instr);
	pos = len;

	if (len >= box_width) {
		show_x = len - box_width + 1;
		input_x = box_width - 1;
		for (i = 0; i < box_width - 1; i++)
			waddch(dialog, instr[show_x + i]);
	} else {
		show_x = 0;
		input_x = len;
		waddstr(dialog, instr);
	}

	wmove(dialog, box_y, box_x + input_x);

	wrefresh(dialog);

	while (key != KEY_ESC) {
		key = wgetch(dialog);

		if (button == -1) {	/* Input box selected */
			switch (key) {
			case TAB:
			case KEY_UP:
			case KEY_DOWN:
				break;
			case KEY_BACKSPACE:
			case 127:
				if (pos) {
					wattrset(dialog, dlg.inputbox.atr);
					if (input_x == 0) {
						show_x--;
					} else
						input_x--;

					if (pos < len) {
						for (i = pos - 1; i < len; i++) {
							instr[i] = instr[i+1];
						}
					}

					pos--;
					len--;
					instr[len] = '\0';
					wmove(dialog, box_y, box_x);
					for (i = 0; i < box_width; i++) {
						if (!instr[show_x + i]) {
							waddch(dialog, ' ');
							break;
						}
						waddch(dialog, instr[show_x + i]);
					}
					wmove(dialog, box_y, input_x + box_x);
					wrefresh(dialog);
				}
				continue;
			case KEY_LEFT:
				if (pos > 0) {
					if (input_x > 0) {
						wmove(dialog, box_y, --input_x + box_x);
					} else if (input_x == 0) {
						show_x--;
						wmove(dialog, box_y, box_x);
						for (i = 0; i < box_width; i++) {
							if (!instr[show_x + i]) {
								waddch(dialog, ' ');
								break;
							}
							waddch(dialog, instr[show_x + i]);
						}
						wmove(dialog, box_y, box_x);
					}
					pos--;
				}
				continue;
			case KEY_RIGHT:
				if (pos < len) {
					if (input_x < box_width - 1) {
						wmove(dialog, box_y, ++input_x + box_x);
					} else if (input_x == box_width - 1) {
						show_x++;
						wmove(dialog, box_y, box_x);
						for (i = 0; i < box_width; i++) {
							if (!instr[show_x + i]) {
								waddch(dialog, ' ');
								break;
							}
							waddch(dialog, instr[show_x + i]);
						}
						wmove(dialog, box_y, input_x + box_x);
					}
					pos++;
				}
				continue;
			default:
				if (key < 0x100 && isprint(key)) {
					if (len < MAX_LEN) {
						wattrset(dialog, dlg.inputbox.atr);
						if (pos < len) {
							for (i = len; i > pos; i--)
								instr[i] = instr[i-1];
							instr[pos] = key;
						} else {
							instr[len] = key;
						}
						pos++;
						len++;
						instr[len] = '\0';

						if (input_x == box_width - 1) {
							show_x++;
						} else {
							input_x++;
						}

						wmove(dialog, box_y, box_x);
						for (i = 0; i < box_width; i++) {
							if (!instr[show_x + i]) {
								waddch(dialog, ' ');
								break;
							}
							waddch(dialog, instr[show_x + i]);
						}
						wmove(dialog, box_y, input_x + box_x);
						wrefresh(dialog);
					} else
						flash();	/* Alarm user about overflow */
					continue;
				}
			}
		}
		switch (key) {
		case 'O':
		case 'o':
			delwin(dialog);
			return 0;
		case 'H':
		case 'h':
			delwin(dialog);
			return 1;
		case KEY_UP:
		case KEY_LEFT:
			switch (button) {
			case -1:
				button = 1;	/* Indicates "Help" button is selected */
				print_buttons(dialog, height, width, 1);
				break;
			case 0:
				button = -1;	/* Indicates input box is selected */
				print_buttons(dialog, height, width, 0);
				wmove(dialog, box_y, box_x + input_x);
				wrefresh(dialog);
				break;
			case 1:
				button = 0;	/* Indicates "OK" button is selected */
				print_buttons(dialog, height, width, 0);
				break;
			}
			break;
		case TAB:
		case KEY_DOWN:
		case KEY_RIGHT:
			switch (button) {
			case -1:
				button = 0;	/* Indicates "OK" button is selected */
				print_buttons(dialog, height, width, 0);
				break;
			case 0:
				button = 1;	/* Indicates "Help" button is selected */
				print_buttons(dialog, height, width, 1);
				break;
			case 1:
				button = -1;	/* Indicates input box is selected */
				print_buttons(dialog, height, width, 0);
				wmove(dialog, box_y, box_x + input_x);
				wrefresh(dialog);
				break;
			}
			break;
		case ' ':
		case '\n':
			delwin(dialog);
			return (button == -1 ? 0 : button);
		case 'X':
		case 'x':
			key = KEY_ESC;
			break;
		case KEY_ESC:
			key = on_key_esc(dialog);
			break;
		case KEY_RESIZE:
			delwin(dialog);
			on_key_resize();
			goto do_resize;
		}
	}

	delwin(dialog);
	return KEY_ESC;		/* ESC pressed */
}
