/* vi: set sw=4 ts=4: */
/*
 *  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, "  Ok  ", y, x, selected==0);
    print_button (dialog, " 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, scroll = 0, key = 0, button = -1;
    char *instr = dialog_input_result;
    WINDOW *dialog;

    /* center dialog box on screen */
    x = (COLS - width) / 2;
    y = (LINES - 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, dialog_attr, border_attr);
    wattrset (dialog, border_attr);
    mvwaddch (dialog, height-3, 0, ACS_LTEE);
    for (i = 0; i < width - 2; i++)
	waddch (dialog, ACS_HLINE);
    wattrset (dialog, dialog_attr);
    waddch (dialog, ACS_RTEE);

    if (title != NULL && strlen(title) >= width-2 ) {
	/* truncate long title -- mec */
	char * title2 = malloc(width-2+1);
	memcpy( title2, title, width-2 );
	title2[width-2] = '\0';
	title = title2;
    }

    if (title != NULL) {
	wattrset (dialog, title_attr);
	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
	waddstr (dialog, (char *)title);
	waddch (dialog, ' ');
    }

    wattrset (dialog, dialog_attr);
    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,
	      border_attr, dialog_attr);

    print_buttons(dialog, height, width, 0);

    /* Set up the initial value */
    wmove (dialog, box_y, box_x);
    wattrset (dialog, inputbox_attr);

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

    input_x = strlen (instr);

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

    wmove (dialog, box_y, box_x + input_x);

    wrefresh (dialog);

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

	if (button == -1) {	/* Input box selected */
	    switch (key) {
	    case TAB:
	    case KEY_UP:
	    case KEY_DOWN:
		break;
	    case KEY_LEFT:
		continue;
	    case KEY_RIGHT:
		continue;
	    case KEY_BACKSPACE:
	    case 127:
		if (input_x || scroll) {
		    wattrset (dialog, inputbox_attr);
		    if (!input_x) {
			scroll = scroll < box_width - 1 ?
			    0 : scroll - (box_width - 1);
			wmove (dialog, box_y, box_x);
			for (i = 0; i < box_width; i++)
			    waddch (dialog, instr[scroll + input_x + i] ?
				    instr[scroll + input_x + i] : ' ');
			input_x = strlen (instr) - scroll;
		    } else
			input_x--;
		    instr[scroll + input_x] = '\0';
		    mvwaddch (dialog, box_y, input_x + box_x, ' ');
		    wmove (dialog, box_y, input_x + box_x);
		    wrefresh (dialog);
		}
		continue;
	    default:
		if (key < 0x100 && isprint (key)) {
		    if (scroll + input_x < MAX_LEN) {
			wattrset (dialog, inputbox_attr);
			instr[scroll + input_x] = key;
			instr[scroll + input_x + 1] = '\0';
			if (input_x == box_width - 1) {
			    scroll++;
			    wmove (dialog, box_y, box_x);
			    for (i = 0; i < box_width - 1; i++)
				waddch (dialog, instr[scroll + i]);
			} else {
			    wmove (dialog, box_y, input_x++ + box_x);
			    waddch (dialog, key);
			}
			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 "Cancel" 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 "Cancel" 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 = ESC;
	case ESC:
	    break;
	}
    }

    delwin (dialog);
    return -1;			/* ESC pressed */
}
